Java Code Examples for com.sun.source.util.TreePath#getParentPath()

The following examples show how to use com.sun.source.util.TreePath#getParentPath() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: CallHierarchyTasks.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private static TreePath resolveDeclarationContext(TreePath usage) {
    TreePath declaration = usage;
    
    while (declaration != null) {
        switch (declaration.getLeaf().getKind()) {
            case BLOCK:
                if (TreeUtilities.CLASS_TREE_KINDS.contains(declaration.getParentPath().getLeaf().getKind())) {
                    // it is static or instance initializer
                    return declaration;
                }
                break;
            case METHOD:
                return declaration;
            case VARIABLE:
                if (TreeUtilities.CLASS_TREE_KINDS.contains(declaration.getParentPath().getLeaf().getKind())) {
                    // it is field declaration
                    // private int field = init();
                    return declaration;
                }
                break;
        }
        declaration = declaration.getParentPath();
    }
    return null;
}
 
Example 2
Source File: ImplementAllAbstractMethods.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private static TreePath deepTreePath(CompilationInfo info, int offset) {
    TreePath basic = info.getTreeUtilities().pathFor(offset);
    TreePath plusOne = info.getTreeUtilities().pathFor(offset + 1);
    
    TreePath parent = plusOne.getParentPath();
    if (parent == null) {
        return basic;
    }
    if (plusOne.getLeaf().getKind() == Kind.NEW_CLASS &&
        parent.getLeaf().getKind() == Kind.EXPRESSION_STATEMENT) {
        parent = parent.getParentPath();
        if (parent == null) {
            return basic;
        }
    }
    if (parent.getLeaf() == basic.getLeaf()) {
        return plusOne;
    }
    return basic;
}
 
Example 3
Source File: IntroduceMethodFix.java    From netbeans with Apache License 2.0 6 votes vote down vote up
/**
 * Checks whether a duplicate intersects with some of the replacements already made
 */
boolean isDuplicateValid(TreePath duplicateRoot) {
    TreePath parent = duplicateRoot.getParentPath();
    List<Integer> repls = replacements.get(parent.getLeaf());
    if (repls == null) {
        return true;
    }
    List<? extends StatementTree> stmts = IntroduceHint.getStatements(duplicateRoot);
    int o = stmts.indexOf(duplicateRoot.getLeaf());
    int l = repls.size();
    for (int idx = 0; idx < l; idx += 2) {
        if (o < repls.get(idx)) {
            continue;
        }
        if (o <= repls.get(idx + 1)) {
            return false;
        }
    }
    return true;
}
 
Example 4
Source File: Utilities.java    From netbeans with Apache License 2.0 6 votes vote down vote up
/**
 * Finds the entire statement up the tree. For code nested in blocks or control
 * flow statements, find the statement (i.e ExpressionStatement for an ExpressionTree).
 * For initializers and update statements, find that init/update statement nested in for cycle.
 * For expression lambdas, returns the outermost expression.
 * <p/>
 * Returns {@code null} if it cannot find enclosing statement.
 * 
 * @param path where to start
 * @return the nearest statement or entire expression
 */
public static TreePath findStatementOrExpression(TreePath path) {
    while (!isStatement(path.getLeaf())) {
        Tree l = path.getLeaf();
        TreePath next = path.getParentPath();
        if (next == null) {
            return null;
        }
        Tree t = next.getLeaf();
        if (TreeUtilities.CLASS_TREE_KINDS.contains(t.getKind())) {
            return null;
        }
        if (t.getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
            break;
        }
        path = next;
    }
    return path;
}
 
Example 5
Source File: DifferentCaseKindsFix.java    From netbeans with Apache License 2.0 5 votes vote down vote up
@Override
public List<Fix> run(CompilationInfo info, String diagnosticKey, int offset, TreePath treePath, Data<Void> data) {
    if (Utilities.isJDKVersionLower(SWITCH_RULE_PREVIEW_JDK_VERSION) && !CompilerOptionsQuery.getOptions(info.getFileObject()).getArguments().contains("--enable-preview")) {
        return null;
    }
    TreePath parentPath = treePath.getParentPath();
    List<? extends CaseTree> caseTrees = null;
    boolean flag = false;
    if(parentPath.getLeaf().getKind().toString().equals(TreeShims.SWITCH_EXPRESSION)){
        caseTrees = TreeShims.getCases(parentPath.getLeaf());            
    } else {
        flag = true;
        caseTrees = ((SwitchTree) treePath.getParentPath().getLeaf()).getCases();
    }
        boolean completesNormally = false;
        boolean wasDefault = false;
        boolean wasEmpty = false;
        for (CaseTree ct : caseTrees) {
            if (ct.getStatements() == null && TreeShims.getBody(ct) == null) {
                return null;
            } else if (flag && ct.getStatements() != null) {
                if (completesNormally) {
                    if (!wasEmpty) {//fall-through from a non-empty case
                        return null;
                    }
                    if (wasDefault) {//fall-through from default to a case
                        return null;
                    }
                    if (!wasDefault && ct.getExpression() == null) {//fall-through from a case to default
                        return null;
                    }
                }
                completesNormally = Utilities.completesNormally(info, new TreePath(treePath.getParentPath(), ct));
                wasDefault = ct.getExpression() == null;
                wasEmpty = ct.getStatements().isEmpty();
            }
        }      

    return Collections.<Fix>singletonList(new DifferentCaseKindsFix.FixImpl(info, treePath).toEditorFix());
}
 
Example 6
Source File: PreconditionsChecker.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private boolean isIfWithContinueOnly(ContinueTree that) {
    TreePath currentTreePath = this.getCurrentPath();
    TreePath parentPath = currentTreePath.getParentPath();
    Tree parentTree = parentPath.getLeaf();
    if (parentTree.getKind() == Tree.Kind.IF) {
        return true;
    } else if (parentTree.getKind() == Tree.Kind.BLOCK) {
        BlockTree parentBlock = (BlockTree) parentTree;
        if (parentBlock.getStatements().size() == 1) {
            return true;
        }
    }
    return false;
}
 
Example 7
Source File: GoToOppositeAction.java    From netbeans with Apache License 2.0 5 votes vote down vote up
/**
 */
public void run(CompilationController controller) throws IOException {
    controller.toPhase(Phase.RESOLVED);     //cursor position needed
    if (cancelled) {
        return;
    }

    TreePath treePath = controller.getTreeUtilities()
                                  .pathFor(caretPosition);
    if (treePath != null) {
        if (cancelled) {
            return;
        }
        
        TreePath parent = treePath.getParentPath();
        while (parent != null) {
            Tree.Kind parentKind = parent.getLeaf().getKind();
            if ((TreeUtilities.CLASS_TREE_KINDS.contains(parentKind))
                    || (parentKind == Tree.Kind.COMPILATION_UNIT)) {
                break;
            }
            treePath = parent;
            parent = treePath.getParentPath();
        }

    }

    if (treePath != null) {
        if (cancelled) {
            return;
        }

        try {
            element = controller.getTrees().getElement(treePath);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger("global").log(Level.WARNING, null, ex);
        }
    }
}
 
Example 8
Source File: UtilitiesTest.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private void performExitsTest(String code, boolean expected) throws Exception {
    int caretPos = code.indexOf('|');
    code = code.replace("|", "");
    prepareTest(code);
    TreePath tp = info.getTreeUtilities().pathFor(caretPos);
    while (tp != null && !StatementTree.class.isAssignableFrom(tp.getLeaf().getKind().asInterface())) {
        tp = tp.getParentPath();
    }
    assertNotNull(tp);
    boolean result = Utilities.exitsFromAllBranchers(info, tp);
    assertEquals(expected, result);
}
 
Example 9
Source File: ConvertToARM.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private static TreePath findEnclosingTryPath(final TreePath path) {
    TreePath parent = path.getParentPath();
    if (parent == null || parent.getLeaf().getKind() != Kind.BLOCK) {
        return null;
    }
    parent = parent.getParentPath();
    if (parent == null || parent.getLeaf().getKind() != Kind.TRY) {
        return null;
    }
    return parent;
}
 
Example 10
Source File: TreeUtils.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public static TreePath findClass(TreePath path) {
    while (path != null) {
        if (TreeUtilities.CLASS_TREE_KINDS.contains(path.getLeaf().getKind())) {
            return path;
        }
        path = path.getParentPath();
    }
    return null;
}
 
Example 11
Source File: ThrowableNotThrown.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private static TreePath findEnclosingMethodPath(TreePath path) {
    TreePath enclosingMethodPath = path;
    TreePath nextPath = enclosingMethodPath.getParentPath();
    Tree.Kind kind;
    do {
        Tree leaf = nextPath.getLeaf();
        enclosingMethodPath = nextPath;
        nextPath = nextPath.getParentPath();
        kind = leaf.getKind();
    } while (nextPath != null && !(kind == Tree.Kind.METHOD || kind == Tree.Kind.CLASS));
    return enclosingMethodPath;
}
 
Example 12
Source File: Utilities.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public static TreePath getPathElementOfKind(Set<Tree.Kind> kinds, TreePath path) {
    while (path != null) {
        if (kinds.contains(path.getLeaf().getKind()))
            return path;
        path = path.getParentPath();
    }
    return null;        
}
 
Example 13
Source File: IntroduceConstantFix.java    From netbeans with Apache License 2.0 5 votes vote down vote up
static TreePath findAcceptableConstantTarget(CompilationInfo info, TreePath from) {
    boolean compileTimeConstant = info.getTreeUtilities().isCompileTimeConstantExpression(from);
    while (from != null) {
        if (TreeUtilities.CLASS_TREE_KINDS.contains(from.getLeaf().getKind())) {
            if (from.getParentPath().getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
                return from;
            }
            if (compileTimeConstant || ((ClassTree) from.getLeaf()).getModifiers().getFlags().contains(Modifier.STATIC)) {
                return from;
            }
        }
        from = from.getParentPath();
    }
    return null;
}
 
Example 14
Source File: IntroduceHint.java    From netbeans with Apache License 2.0 4 votes vote down vote up
public static TreePath validateSelection(CompilationInfo ci, int start, int end, Set<TypeKind> ignoredTypes) {
    int[] span = TreeUtils.ignoreWhitespaces(ci, Math.min(start, end), Math.max(start, end));

    start = span[0];
    end   = span[1];
    
    TreePath tp = ci.getTreeUtilities().pathFor((start + end) / 2 + 1);

    for ( ; tp != null; tp = tp.getParentPath()) {
        Tree leaf = tp.getLeaf();

        if (   !ExpressionTree.class.isAssignableFrom(leaf.getKind().asInterface())
            && (leaf.getKind() != Kind.VARIABLE || ((VariableTree) leaf).getInitializer() == null))
           continue;

        long treeStart = ci.getTrees().getSourcePositions().getStartPosition(ci.getCompilationUnit(), leaf);
        long treeEnd   = ci.getTrees().getSourcePositions().getEndPosition(ci.getCompilationUnit(), leaf);

        if (treeStart != start || treeEnd != end) {
            continue;
        }

        TypeMirror type = ci.getTrees().getTypeMirror(tp);

        if (type != null && type.getKind() == TypeKind.ERROR) {
            type = ci.getTrees().getOriginalType((ErrorType) type);
        }

        if (type == null || ignoredTypes.contains(type.getKind()))
            continue;

        if(tp.getLeaf().getKind() == Kind.ASSIGNMENT)
            continue;

        if (tp.getLeaf().getKind() == Kind.ANNOTATION)
            continue;

        if (!TreeUtils.isInsideClass(tp))
            return null;

        TreePath candidate = tp;

        tp = tp.getParentPath();

        while (tp != null) {
            switch (tp.getLeaf().getKind()) {
                case VARIABLE:
                    VariableTree vt = (VariableTree) tp.getLeaf();
                    if (vt.getInitializer() == leaf) {
                        return candidate;
                    } else {
                        return null;
                    }
                case NEW_CLASS:
                    NewClassTree nct = (NewClassTree) tp.getLeaf();
                    
                    if (nct.getIdentifier().equals(candidate.getLeaf())) { //avoid disabling hint ie inside of anonymous class higher in treepath
                        for (Tree p : nct.getArguments()) {
                            if (p == leaf) {
                                return candidate;
                            }
                        }

                        return null;
                    }
            }

            leaf = tp.getLeaf();
            tp = tp.getParentPath();
        }

        return candidate;
    }

    return null;
}
 
Example 15
Source File: UnlockOutsideFinally.java    From netbeans with Apache License 2.0 4 votes vote down vote up
@TriggerPatterns({
    @TriggerPattern(value="$lock.lock(); $otherStats$; try { $statements$; $lock.unlock(); $rest$; } catch $catches$ finally { $finstats$; } ",
                    constraints=@ConstraintVariableType(variable="$lock", type="java.util.concurrent.locks.Lock")),
    @TriggerPattern(value="$lock.lock(); $otherStats$; try { $statements$; $lock.unlock(); $rest$; } catch $catches$",
                    constraints=@ConstraintVariableType(variable="$lock", type="java.util.concurrent.locks.Lock")),
    @TriggerPattern(value="$lock.lock(); $otherStats$; try { $statements$; } catch $catches$ catch($excType $var) { $catchStats1$; $lock.unlock(); $catchStats2$; } catch $catches2$ finally { $finstmts$; }",
                    constraints=@ConstraintVariableType(variable="$lock", type="java.util.concurrent.locks.Lock")),
})
@NbBundle.Messages({
    "ERR_UnlockOutsideTryFinally=Lock.lock() not unlocked in finally",
    "FIX_UnlockOutsideTryFinally=Wrap by try-finally",
    "MSG_ExtraUnlock=Extra unlock() call; lock is already released in finally"
})
public static ErrorDescription unlockInsideTry(HintContext ctx) {
    TreePath fin = ctx.getVariables().get("$lock$1");
    if (fin == null) {
        return null;
    }
    TreePath parent = fin.getParentPath();
    if (parent.getLeaf().getKind() != Tree.Kind.MEMBER_SELECT) {
        return null;
    }
    parent = parent.getParentPath();
    if (parent == null || parent.getLeaf().getKind() != Tree.Kind.METHOD_INVOCATION) {
        return null;
    }
    TreePath tPath = parent.getParentPath();
    while (tPath != null && tPath.getLeaf().getKind() != Tree.Kind.TRY) {
        if (tPath.getLeaf().getKind() == Tree.Kind.METHOD || 
            tPath.getLeaf().getKind() == Tree.Kind.CLASS) {
            return null;
        }
        tPath = tPath.getParentPath();
    }
    if (tPath == null) {
        return null;
    }
    TryTree tt = (TryTree)tPath.getLeaf();
    Fix f = null;
    
    String displayName = null;
    
    if (tt.getFinallyBlock() != null) {
        
        TreePath finBlockPath = new TreePath(tPath, tt.getFinallyBlock());
        Collection<? extends Occurrence> occ = Matcher.create(ctx.getInfo()).
            setSearchRoot(finBlockPath).
            match(
                Pattern.createSimplePattern(parent)
            );
        if (!occ.isEmpty()) {
            f = new MoveUnlockFix(
                    TreePathHandle.create(parent, ctx.getInfo()),
                    null).toEditorFix();
            displayName = Bundle.MSG_ExtraUnlock();
        }
    }
    if (f == null) {
        displayName = Bundle.ERR_UnlockOutsideTryFinally();
        f = new MoveUnlockFix(
                TreePathHandle.create(parent, ctx.getInfo()),
                TreePathHandle.create(tPath, ctx.getInfo())).toEditorFix();
    }
    
    return ErrorDescriptionFactory.forName(ctx, parent, displayName, f);
}
 
Example 16
Source File: JavacTrees.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private Env<AttrContext> getAttrContext(TreePath path) {
        if (!(path.getLeaf() instanceof JCTree))  // implicit null-check
            throw new IllegalArgumentException();

        // if we're being invoked via from a JSR199 client, we need to make sure
        // all the classes have been entered; if we're being invoked from JSR269,
        // then the classes will already have been entered.
        if (javacTaskImpl != null) {
            try {
                javacTaskImpl.enter(null);
            } catch (IOException e) {
                throw new Error("unexpected error while entering symbols: " + e);
            }
        }


        JCCompilationUnit unit = (JCCompilationUnit) path.getCompilationUnit();
        Copier copier = new Copier(treeMaker.forToplevel(unit));

        Env<AttrContext> env = null;
        JCMethodDecl method = null;
        JCVariableDecl field = null;

        List<Tree> l = List.nil();
        TreePath p = path;
        while (p != null) {
            l = l.prepend(p.getLeaf());
            p = p.getParentPath();
        }

        for ( ; l.nonEmpty(); l = l.tail) {
            Tree tree = l.head;
            switch (tree.getKind()) {
                case COMPILATION_UNIT:
//                    System.err.println("COMP: " + ((JCCompilationUnit)tree).sourcefile);
                    env = enter.getTopLevelEnv((JCCompilationUnit)tree);
                    break;
                case ANNOTATION_TYPE:
                case CLASS:
                case ENUM:
                case INTERFACE:
//                    System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName());
                    env = enter.getClassEnv(((JCClassDecl)tree).sym);
                    break;
                case METHOD:
//                    System.err.println("METHOD: " + ((JCMethodDecl)tree).sym.getSimpleName());
                    method = (JCMethodDecl)tree;
                    break;
                case VARIABLE:
//                    System.err.println("FIELD: " + ((JCVariableDecl)tree).sym.getSimpleName());
                    field = (JCVariableDecl)tree;
                    break;
                case BLOCK: {
//                    System.err.println("BLOCK: ");
                    if (method != null)
                        env = memberEnter.getMethodEnv(method, env);
                    JCTree body = copier.copy((JCTree)tree, (JCTree) path.getLeaf());
                    env = attribStatToTree(body, env, copier.leafCopy);
                    return env;
                }
                default:
//                    System.err.println("DEFAULT: " + tree.getKind());
                    if (field != null && field.getInitializer() == tree) {
                        env = memberEnter.getInitEnv(field, env);
                        JCExpression expr = copier.copy((JCExpression)tree, (JCTree) path.getLeaf());
                        env = attribExprToTree(expr, env, copier.leafCopy);
                        return env;
                    }
            }
        }
        return field != null ? memberEnter.getInitEnv(field, env) : env;
    }
 
Example 17
Source File: StaticImport.java    From netbeans with Apache License 2.0 4 votes vote down vote up
@TriggerTreeKind(Kind.MEMBER_SELECT)
public static List<ErrorDescription> run(HintContext ctx) {
    CompilationInfo info = ctx.getInfo();
    TreePath treePath = ctx.getPath();

    Element e = info.getTrees().getElement(treePath);
    EnumSet<ElementKind> supportedTypes = EnumSet.of(ElementKind.METHOD, ElementKind.ENUM_CONSTANT, ElementKind.FIELD);
    if (e == null || !e.getModifiers().contains(Modifier.STATIC) || !supportedTypes.contains(e.getKind())) {
        return null;
    }

    if (ElementKind.METHOD.equals(e.getKind())) {
        TreePath mitp = treePath.getParentPath();
        if (mitp == null || mitp.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
        return null;
    }
        if (((MethodInvocationTree) mitp.getLeaf()).getMethodSelect() != treePath.getLeaf()) {
        return null;
    }
        List<? extends Tree> typeArgs = ((MethodInvocationTree) mitp.getLeaf()).getTypeArguments();
        if (typeArgs != null && !typeArgs.isEmpty()) {
        return null;
    }
    }
    Element enclosingEl = e.getEnclosingElement();
    if (enclosingEl == null) {
        return null;
    }
    String sn = e.getSimpleName().toString();
    // rules out .class, but who knows what keywords will be abused in the future.
    if (SourceVersion.isKeyword(sn)) {
        return null;
    }
    TreePath cc = getContainingClass(treePath);
    if (cc == null){
        return null;
    }
    Element klass = info.getTrees().getElement(cc);
    if (klass == null || klass.getKind() != ElementKind.CLASS) {
        return null;
    }
    String fqn = null;
    String fqn1 = getFqn(info, e);
    if (!isSubTypeOrInnerOfSubType(info, klass, enclosingEl) && !isStaticallyImported(info, fqn1)) {
        if (hasMethodNameClash(info, klass, sn) || hasStaticImportSimpleNameClash(info, sn)) {
            return null;
        }
        fqn = fqn1;
    }
    Scope currentScope = info.getTrees().getScope(treePath);
    TypeMirror enclosingType = e.getEnclosingElement().asType();
    if (enclosingType == null || enclosingType.getKind() != TypeKind.DECLARED || !info.getTrees().isAccessible(currentScope, e, (DeclaredType) enclosingType)) {
        return null;
    }
    String desc = NbBundle.getMessage(StaticImport.class, "ERR_StaticImport");
    ErrorDescription ed = ErrorDescriptionFactory.forTree(ctx, treePath, desc, new FixImpl(TreePathHandle.create(treePath, info), fqn, sn).toEditorFix());
    if (ctx.isCanceled()) {
        return null;
    }
    return Collections.singletonList(ed);
}
 
Example 18
Source File: SourceCodeAnalysisImpl.java    From openjdk-jdk9 with GNU General Public License v2.0 4 votes vote down vote up
private ImportTree findImport(TreePath tp) {
    while (tp != null && tp.getLeaf().getKind() != Kind.IMPORT) {
        tp = tp.getParentPath();
    }
    return tp != null ? (ImportTree)tp.getLeaf() : null;
}
 
Example 19
Source File: ArithmeticUtilities.java    From netbeans with Apache License 2.0 4 votes vote down vote up
/**
 * Evaluates the constant expression encoded by tree at 'tp' path. See {@link ArithmeticUtilities} for more information.
 * <b>Always</b> check the result value for instanceof before using the value. Without the check, only != null test
 * is valid and has meaning "the expression is known to be constant".
 * 
 * @param info context
 * @param tp tree path for the expression
 * @param resolveCompileTimeConstants if false, symbol resolution is enabled
 * @param enhanced if true, improved analysis is enabled. If false, strict JLS rules apply.
 * @return 
 */
public static Object compute(CompilationInfo info, TreePath tp, boolean resolveCompileTimeConstants, boolean enhanced) {
    // examine parent, if the expression is in some condition/cycle, it might be already evaluated
    boolean save = false;
    ElementValue v = null;
    Map<Object, ElementValue> cache = null;
    if (tp.getParentPath() != null) {
        Tree parentL = tp.getParentPath().getLeaf();
        switch (parentL.getKind()) {
            case IF: 
            case DO_WHILE_LOOP:
            case CONDITIONAL_EXPRESSION:
            case FOR_LOOP:
            case ASSIGNMENT:
            case VARIABLE:
                save = true;
                break;
            case ASSERT: 
                save = ((AssertTree)parentL).getCondition() == tp.getLeaf();
                break;
        }
        
        if (save) {
            cache = VisitorImpl.getValueCache(info);
            v = cache.get(tp.getLeaf());
            if (v != null) {
                if (enhanced && v.constant != null) {
                    return v.constant == UNKNOWN ? null : v.constant;
                } else if (!enhanced && v.jlsConstant != null) {
                    return v.jlsConstant == UNKNOWN ? null : v.jlsConstant;
                }
            }
            
        }
    }
    Object o;
    try {
        o = new VisitorImpl(info, resolveCompileTimeConstants, enhanced).scan(tp, null);
    } catch (ArithmeticException | IndexOutOfBoundsException | IllegalArgumentException ex) {
        o = null;
    }
    if (save) {
        if (v == null) {
            v = new ElementValue();
            cache.put(tp.getLeaf(), v);
        }
        if (enhanced) {
            v.constant = o == null ? UNKNOWN : o;
        } else {
            v.jlsConstant = o == null ? UNKNOWN : o;
        }
    }
    return o;
    
}
 
Example 20
Source File: FlowTest.java    From netbeans with Apache License 2.0 3 votes vote down vote up
private void performDefinitellyAssignmentTest(String code, boolean allowErrors, boolean definitellyAssigned) throws Exception {
    int varPos = code.indexOf('`');
    
    code = code.replace("`", "");
    
    assertTrue(varPos >= 0);
    
    int[] span = new int[2];

    code = TestUtilities.detectOffsets(code, span, "\\|");

    prepareTest(code, allowErrors);

    TreePath tp = info.getTreeUtilities().pathFor((span[0] + span[1]) / 2);
    
    while (tp != null) {
        long s = info.getTrees().getSourcePositions().getStartPosition(tp.getCompilationUnit(), tp.getLeaf());
        long e = info.getTrees().getSourcePositions().getEndPosition(tp.getCompilationUnit(), tp.getLeaf());
        
        if (span[0] == s && span[1] == e) break;
        
        tp = tp.getParentPath();
    }
    
    assertNotNull(tp);
    
    TreePath var = info.getTreeUtilities().pathFor(varPos);
    Element el = info.getTrees().getElement(var);
    
    assertNotNull(el);
    assertEquals(ElementKind.LOCAL_VARIABLE, el.getKind());
    
    boolean actual = Flow.definitellyAssigned(info, (VariableElement) el, Collections.singletonList(tp), new AtomicBoolean());
    
    assertEquals(definitellyAssigned, actual);
}