Java Code Examples for com.sun.tools.javac.code.Symbol

The following examples show how to use com.sun.tools.javac.code.Symbol. These examples are extracted from open source projects. 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
/**
 * Preprocess a diagnostic argument. A type/symbol argument is
 * preprocessed by specialized type/symbol preprocessors.
 *
 * @param arg the argument to be translated
 */
protected void preprocessArgument(Object arg) {
    if (arg instanceof Type) {
        preprocessType((Type)arg);
    }
    else if (arg instanceof Symbol) {
        preprocessSymbol((Symbol)arg);
    }
    else if (arg instanceof JCDiagnostic) {
        preprocessDiagnostic((JCDiagnostic)arg);
    }
    else if (arg instanceof Iterable<?> && !(arg instanceof Path)) {
        for (Object o : (Iterable<?>)arg) {
            preprocessArgument(o);
        }
    }
}
 
Example 2
Source Project: manifold   Source File: JavacBinder.java    License: Apache License 2.0 6 votes vote down vote up
private Symbol.MethodSymbol resolveOperatorMethod( Type left, Type right, Tag operator )
{
  // Handle operator overloading

  boolean swapped = false;
  Symbol.MethodSymbol overloadOperator = ManAttr.resolveOperatorMethod( _types, operator, left, right );
  if( overloadOperator == null && ManAttr.isCommutative( operator ) )
  {
    overloadOperator = ManAttr.resolveOperatorMethod( _types, operator, right, left );
    swapped = true;
  }
  if( overloadOperator != null )
  {
    return new OverloadOperatorSymbol( overloadOperator, swapped );
  }

  return null;
}
 
Example 3
Source Project: openjdk-jdk9   Source File: ClassDocImpl.java    License: GNU General Public License v2.0 6 votes vote down vote up
/**
 * Adds all inner classes of this class, and their
 * inner classes recursively, to the list l.
 */
void addAllClasses(ListBuffer<ClassDocImpl> l, boolean filtered) {
    try {
        if (isSynthetic()) return;
        // sometimes synthetic classes are not marked synthetic
        if (!JavadocTool.isValidClassName(tsym.name.toString())) return;
        if (filtered && !env.shouldDocument(tsym)) return;
        if (l.contains(this)) return;
        l.append(this);
        List<ClassDocImpl> more = List.nil();
        for (Symbol sym : tsym.members().getSymbols(NON_RECURSIVE)) {
            if (sym != null && sym.kind == TYP) {
                ClassSymbol s = (ClassSymbol)sym;
                ClassDocImpl c = env.getClassDoc(s);
                if (c.isSynthetic()) continue;
                if (c != null) more = more.prepend(c);
            }
        }
        // this extra step preserves the ordering from oldjavadoc
        for (; more.nonEmpty(); more=more.tail) {
            more.head.addAllClasses(l, filtered);
        }
    } catch (CompletionFailure e) {
        // quietly ignore completion failures
    }
}
 
Example 4
/**
 * Preprocess a diagnostic argument. A type/symbol argument is
 * preprocessed by specialized type/symbol preprocessors.
 *
 * @param arg the argument to be translated
 */
protected void preprocessArgument(Object arg) {
    if (arg instanceof Type) {
        preprocessType((Type)arg);
    }
    else if (arg instanceof Symbol) {
        preprocessSymbol((Symbol)arg);
    }
    else if (arg instanceof JCDiagnostic) {
        preprocessDiagnostic((JCDiagnostic)arg);
    }
    else if (arg instanceof Iterable<?>) {
        for (Object o : (Iterable<?>)arg) {
            preprocessArgument(o);
        }
    }
}
 
Example 5
Source Project: jdk8u60   Source File: CheckAttributedTree.java    License: GNU General Public License v2.0 6 votes vote down vote up
Field checkFields(JCTree t) {
    List<Field> fieldsToCheck = treeUtil.getFieldsOfType(t,
            excludedFields,
            Symbol.class,
            Type.class);
    for (Field f : fieldsToCheck) {
        try {
            if (f.get(t) == null) {
                return f;
            }
        }
        catch (IllegalAccessException e) {
            System.err.println("Cannot read field: " + f);
            //swallow it
        }
    }
    return null;
}
 
Example 6
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
    super.visitMethodInvocation(node, p);
    JCMethodInvocation apply = (JCMethodInvocation)node;
    JCIdent ident = (JCIdent)apply.meth;
    Symbol oldSym = ident.sym;
    if (!oldSym.isConstructor()) {
        Object[] staticArgs = new Object[arity.arity];
        for (int i = 0; i < arity.arity ; i++) {
            staticArgs[i] = saks[i].getValue(syms, names, types);
        }
        ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
                oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
    }
    return null;
}
 
Example 7
Source Project: openjdk-8   Source File: ResolveHarness.java    License: GNU General Public License v2.0 6 votes vote down vote up
@Override
void process(Diagnostic<? extends JavaFileObject> diagnostic) {
    Element siteSym = getSiteSym(diagnostic);
    if (siteSym.getSimpleName().length() != 0 &&
            ((Symbol)siteSym).outermostClass().getAnnotation(TraceResolve.class) == null) {
        return;
    }
    int candidateIdx = 0;
    for (JCDiagnostic d : subDiagnostics(diagnostic)) {
        boolean isMostSpecific = candidateIdx++ == mostSpecific(diagnostic);
        VerboseCandidateSubdiagProcessor subProc =
                new VerboseCandidateSubdiagProcessor(isMostSpecific, phase(diagnostic), success(diagnostic));
        if (subProc.matches(d)) {
            subProc.process(d);
        } else {
            throw new AssertionError("Bad subdiagnostic: " + d.getCode());
        }
    }
}
 
Example 8
Source Project: NullAway   Source File: NullAway.java    License: MIT License 6 votes vote down vote up
@Override
public Description matchNewClass(NewClassTree tree, VisitorState state) {
  if (!matchWithinClass) {
    return Description.NO_MATCH;
  }
  Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(tree);
  if (methodSymbol == null) {
    throw new RuntimeException("not expecting unresolved method here");
  }
  List<? extends ExpressionTree> actualParams = tree.getArguments();
  if (tree.getClassBody() != null && actualParams.size() > 0) {
    // passing parameters to constructor of anonymous class
    // this constructor just invokes the constructor of the superclass, and
    // in the AST does not have the parameter nullability annotations from the superclass.
    // so, treat as if the superclass constructor is being invoked directly
    // see https://github.com/uber/NullAway/issues/102
    methodSymbol = getSymbolOfSuperConstructor(methodSymbol, state);
  }
  return handleInvocation(tree, state, methodSymbol, actualParams);
}
 
Example 9
Source Project: NullAway   Source File: RestrictiveAnnotationHandler.java    License: MIT License 6 votes vote down vote up
@Override
public boolean onOverrideMayBeNullExpr(
    NullAway analysis, ExpressionTree expr, VisitorState state, boolean exprMayBeNull) {
  if (expr.getKind().equals(Tree.Kind.METHOD_INVOCATION)) {
    Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol((MethodInvocationTree) expr);
    if (NullabilityUtil.isUnannotated(methodSymbol, config)) {
      // with the generated-as-unannotated option enabled, we want to ignore
      // annotations in generated code
      if (config.treatGeneratedAsUnannotated() && NullabilityUtil.isGenerated(methodSymbol)) {
        return exprMayBeNull;
      } else {
        return Nullness.hasNullableAnnotation(methodSymbol, config) || exprMayBeNull;
      }
    } else {
      return exprMayBeNull;
    }
  }
  return exprMayBeNull;
}
 
Example 10
Source Project: manifold   Source File: ManResolve.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Allow @Jailbreak to expose otherwise inaccessible features
 */
@Override
public boolean isAccessible( Env<AttrContext> env, Type site, Symbol sym, boolean checkInner )
{
  boolean accessible = super.isAccessible( env, site, sym, checkInner );
  if( accessible )
  {
    return true;
  }

  if( isJailbreak( sym ) )
  {
    return true;
  }
  return isJailbreak( env.tree );
}
 
Example 11
Source Project: openjdk-8   Source File: BasicAnnoTests.java    License: GNU General Public License v2.0 6 votes vote down vote up
public Void scan(Element elem, Void ignore) {
    AnnotationMirror test = getAnnotation(elem, Test.class.getName().replace('$', '.'));
    if (test != null) {
        out.println("Test: " + elem + " " + test);
        TestTypeScanner s = new TestTypeScanner(elem, test);
        s.scan(elem.asType(), null);
        if (getPosn(test) >= s.count)
            error(elem, "position " + getPosn(test) + " not found");
        if (!s.found) {
            dprinter.printSymbol("element", (Symbol) elem);
            dprinter.printType("type", (Type) elem.asType());
        }
        out.println();
    }
    return super.scan(elem, ignore);
}
 
Example 12
/**
 * Preprocess a diagnostic argument. A type/symbol argument is
 * preprocessed by specialized type/symbol preprocessors.
 *
 * @param arg the argument to be translated
 */
protected void preprocessArgument(Object arg) {
    if (arg instanceof Type) {
        preprocessType((Type)arg);
    }
    else if (arg instanceof Symbol) {
        preprocessSymbol((Symbol)arg);
    }
    else if (arg instanceof JCDiagnostic) {
        preprocessDiagnostic((JCDiagnostic)arg);
    }
    else if (arg instanceof Iterable<?>) {
        for (Object o : (Iterable<?>)arg) {
            preprocessArgument(o);
        }
    }
}
 
Example 13
/** Resolve an identifier.
 * @param msym      The module in which the search should be performed
 * @param name      The identifier to resolve
 */
public Symbol resolveIdent(ModuleSymbol msym, String name) {
    if (name.equals(""))
        return syms.errSymbol;
    JavaFileObject prev = log.useSource(null);
    try {
        JCExpression tree = null;
        for (String s : name.split("\\.", -1)) {
            if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords
                return syms.errSymbol;
            tree = (tree == null) ? make.Ident(names.fromString(s))
                                  : make.Select(tree, names.fromString(s));
        }
        JCCompilationUnit toplevel =
            make.TopLevel(List.nil());
        toplevel.modle = msym;
        toplevel.packge = msym.unnamedPackage;
        return attr.attribIdent(tree, toplevel);
    } finally {
        log.useSource(prev);
    }
}
 
Example 14
Source Project: besu   Source File: DoNotCreateSecureRandomDirectly.java    License: Apache License 2.0 5 votes vote down vote up
@Override
public Description matchNewClass(final NewClassTree tree, final VisitorState state) {
  final Symbol sym = ASTHelpers.getSymbol(tree.getIdentifier());
  if (sym != null && sym.toString().equals("java.security.SecureRandom")) {
    return describeMatch(tree);
  }

  return Description.NO_MATCH;
}
 
Example 15
Source Project: hottub   Source File: TypeMaker.java    License: GNU General Public License v2.0 5 votes vote down vote up
/**
 * Return the formal type parameters of a class or method as an
 * angle-bracketed string.  Each parameter is a type variable with
 * optional bounds.  Class names are qualified if "full" is true.
 * Return "" if there are no type parameters or we're hiding generics.
 */
static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
    if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
        return "";
    }
    StringBuilder s = new StringBuilder();
    for (Type t : sym.type.getTypeArguments()) {
        s.append(s.length() == 0 ? "<" : ", ");
        s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
    }
    s.append(">");
    return s.toString();
}
 
Example 16
/**
 * Return the class, interface, method, or constructor within
 * which this type variable is declared.
 */
public ProgramElementDoc owner() {
    Symbol osym = type.tsym.owner;
    if ((osym.kind & Kinds.TYP) != 0) {
        return env.getClassDoc((ClassSymbol)osym);
    }
    Names names = osym.name.table.names;
    if (osym.name == names.init) {
        return env.getConstructorDoc((MethodSymbol)osym);
    } else {
        return env.getMethodDoc((MethodSymbol)osym);
    }
}
 
Example 17
Source Project: manifold   Source File: ExtensionTransformer.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * If the binding expression is of the form `A b` where `A` is a Float or Double *literal* and `b` defines a
 * `R postfixBind(String)` where `R` is the same return type as the original binding expression, then get the
 * token that was parsed for the Float or Double literal and use the String version of `postfixBind()`. This has
 * the effect of preserving the value of the token, where otherwise it can be lost due to IEEE floating point
 * encoding.
 */
private Symbol.MethodSymbol favorStringsWithNumberCoercion( JCTree.JCBinary tree, Symbol.MethodSymbol operatorMethod )
{
  String operatorMethodName = operatorMethod.name.toString();
  if( !operatorMethodName.equals( "postfixBind" ) )
  {
    return operatorMethod;
  }

  if( tree.lhs instanceof JCTree.JCLiteral &&
      (tree.lhs.getKind() == Tree.Kind.FLOAT_LITERAL || tree.lhs.getKind() == Tree.Kind.DOUBLE_LITERAL) )
  {
    Type rhsType = tree.rhs.type;
    Symbol.MethodSymbol postfixBinding_string = ManAttr.getMethodSymbol(
      _tp.getTypes(), rhsType, _tp.getSymtab().stringType, operatorMethodName, (Symbol.ClassSymbol)rhsType.tsym, 1 );

    if( postfixBinding_string != null &&
        postfixBinding_string.getParameters().get( 0 ).type.tsym == _tp.getSymtab().stringType.tsym &&
        postfixBinding_string.getReturnType().equals( operatorMethod.getReturnType() ) )
    {
      // since the source may be preprocessed we attempt to get it in its preprocessed form
      CharSequence source = ManParserFactory.getSource( _tp.getCompilationUnit().getSourceFile() );
      int start = tree.lhs.pos;
      int end = tree.lhs.pos().getEndPosition( ((JCTree.JCCompilationUnit)_tp.getCompilationUnit()).endPositions );
      String token = source.subSequence( start, end ).toString();
      if( token.endsWith( "d" ) || token.endsWith( "f" ) )
      {
        token = token.substring( 0, token.length()-1 );
      }
      JCTree.JCLiteral temp = (JCTree.JCLiteral)tree.lhs;
      tree.lhs = _tp.getTreeMaker().Literal( token );
      tree.lhs.type = _tp.getSymtab().stringType;
      tree.lhs.pos = temp.pos;

      return postfixBinding_string;
    }
  }
  return operatorMethod;
}
 
Example 18
Source Project: openjdk-8   Source File: JavacTrees.java    License: GNU General Public License v2.0 5 votes vote down vote up
public boolean isAccessible(Scope scope, Element member, DeclaredType type) {
    if (scope instanceof JavacScope
            && member instanceof Symbol
            && type instanceof com.sun.tools.javac.code.Type) {
        Env<AttrContext> env = ((JavacScope) scope).env;
        return resolve.isAccessible(env, (com.sun.tools.javac.code.Type)type, (Symbol)member, true);
    } else
        return false;
}
 
Example 19
Source Project: hottub   Source File: LambdaToMethod.java    License: GNU General Public License v2.0 5 votes vote down vote up
/** Make an attributed class instance creation expression.
 *  @param ctype    The class type.
 *  @param args     The constructor arguments.
 *  @param cons     The constructor symbol
 */
JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
    JCNewClass tree = make.NewClass(null,
        null, make.QualIdent(ctype.tsym), args, null);
    tree.constructor = cons;
    tree.type = ctype;
    return tree;
}
 
Example 20
Source Project: manifold   Source File: ManClassWriter.java    License: Apache License 2.0 5 votes vote down vote up
@Override
public void writeClassFile( OutputStream out, Symbol.ClassSymbol c ) throws StringOverflow, IOException, PoolOverflow
{
  JavaFileObject sourceFile = c.sourcefile;
  if( sourceFile instanceof ISelfCompiledFile && ((ISelfCompiledFile)sourceFile).isSelfCompile( c.getQualifiedName().toString() ) )
  {
    out.write( ((ISelfCompiledFile)sourceFile).compile( c.getQualifiedName().toString() ) );
  }
  else
  {
    super.writeClassFile( out, c );
  }
}
 
Example 21
@Override
protected String className(ClassType t, boolean longform, Locale locale) {
    Symbol sym = t.tsym;
    if (sym.name.length() == 0 ||
            !getConfiguration().isEnabled(RichFormatterFeature.SIMPLE_NAMES)) {
        return super.className(t, longform, locale);
    }
    else if (longform)
        return nameSimplifier.simplify(sym).toString();
    else
        return sym.name.toString();
}
 
Example 22
Source Project: openjdk-jdk9   Source File: LambdaToMethod.java    License: GNU General Public License v2.0 5 votes vote down vote up
/** Make an attributed class instance creation expression.
 *  @param ctype    The class type.
 *  @param args     The constructor arguments.
 *  @param cons     The constructor symbol
 */
JCNewClass makeNewClass(Type ctype, List<JCExpression> args, Symbol cons) {
    JCNewClass tree = make.NewClass(null,
        null, make.QualIdent(ctype.tsym), args, null);
    tree.constructor = cons;
    tree.type = ctype;
    return tree;
}
 
Example 23
Source Project: TencentKona-8   Source File: LambdaToMethod.java    License: GNU General Public License v2.0 5 votes vote down vote up
private JCIdent makeThis(Type type, Symbol owner) {
    VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
            names._this,
            type,
            owner);
    return make.Ident(_this);
}
 
Example 24
boolean currentlyInClass(Symbol csym) {
    for (Frame frame : frameStack) {
        if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) {
            JCClassDecl cdef = (JCClassDecl) frame.tree;
            if (cdef.sym == csym) {
                return true;
            }
        }
    }
    return false;
}
 
Example 25
Source Project: jdk8u60   Source File: LambdaToMethod.java    License: GNU General Public License v2.0 5 votes vote down vote up
private JCExpression deserGetter(String func, Type type, List<Type> argTypes, List<JCExpression> args) {
    MethodType getmt = new MethodType(argTypes, type, List.<Type>nil(), syms.methodClass);
    Symbol getsym = rs.resolveQualifiedMethod(null, attrEnv, syms.serializedLambdaType, names.fromString(func), argTypes, List.<Type>nil());
    return make.Apply(
                List.<JCExpression>nil(),
                make.Select(make.Ident(kInfo.deserParamSym).setType(syms.serializedLambdaType), getsym).setType(getmt),
                args).setType(type);
}
 
Example 26
Source Project: manifold   Source File: ManResolve.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Allow augmented classes to access modules as if defined in both the extended class' module and
 * the extension class' module.
 */
@Override
public boolean isAccessible( Env<AttrContext> env, Symbol.TypeSymbol typeSymbol, boolean checkInner )
{
  boolean accessible = super.isAccessible( env, typeSymbol, checkInner );
  if( accessible )
  {
    return true;
  }

  if( isJailbreakOnType() )
  {
    // handle the case where the class itself is inaccessible:
    //
    // // the *type* must be @Jailbreak as well as the constructor
    // [email protected] PrivateClass privateThing = new [email protected] PrivateClass();
    // privateThing.privateMethod();
    // ...
    return true;
  }

  if( JavacPlugin.IS_JAVA_8 )
  {
    return false;
  }


  // Java 9 +

  JavaFileObject sourceFile = env.toplevel.getSourceFile();
  if( sourceFile instanceof GeneratedJavaStubFileObject )
  {
    // Allow augmented classes to access modules as if defined in both the extended class' module and
    // the extension class' module.
    accessible = true;
  }

  return accessible;
}
 
Example 27
/**
 * Generate an indy method call with given name, type and static bootstrap
 * arguments types
 */
private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
        List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
        Name methName) {
    int prevPos = make.pos;
    try {
        make.at(pos);
        List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
                syms.stringType,
                syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));

        Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
                bsmName, bsm_staticArgs, List.nil());

        DynamicMethodSymbol dynSym =
                new DynamicMethodSymbol(methName,
                                        syms.noSymbol,
                                        bsm.isStatic() ?
                                            ClassFile.REF_invokeStatic :
                                            ClassFile.REF_invokeVirtual,
                                        (MethodSymbol)bsm,
                                        indyType,
                                        staticArgs.toArray());

        JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
        qualifier.sym = dynSym;
        qualifier.type = indyType.getReturnType();

        JCMethodInvocation proxyCall = make.Apply(List.nil(), qualifier, indyArgs);
        proxyCall.type = indyType.getReturnType();
        return proxyCall;
    } finally {
        make.at(prevPos);
    }
}
 
Example 28
Source Project: NullAway   Source File: NullAway.java    License: MIT License 5 votes vote down vote up
@Override
public Description matchLambdaExpression(LambdaExpressionTree tree, VisitorState state) {
  if (!matchWithinClass) {
    return Description.NO_MATCH;
  }
  Symbol.MethodSymbol funcInterfaceMethod =
      NullabilityUtil.getFunctionalInterfaceMethod(tree, state.getTypes());
  // we need to update environment mapping before running the handler, as some handlers
  // (like Rx nullability) run dataflow analysis
  updateEnvironmentMapping(tree, state);
  handler.onMatchLambdaExpression(this, tree, state, funcInterfaceMethod);
  if (NullabilityUtil.isUnannotated(funcInterfaceMethod, config)) {
    return Description.NO_MATCH;
  }
  Description description =
      checkParamOverriding(
          tree.getParameters().stream().map(ASTHelpers::getSymbol).collect(Collectors.toList()),
          funcInterfaceMethod,
          tree,
          null,
          state);
  if (description != Description.NO_MATCH) {
    return description;
  }
  // if the body has a return statement, that gets checked in matchReturn().  We need this code
  // for lambdas with expression bodies
  if (tree.getBodyKind() == LambdaExpressionTree.BodyKind.EXPRESSION
      && funcInterfaceMethod.getReturnType().getKind() != TypeKind.VOID) {
    ExpressionTree resExpr = (ExpressionTree) tree.getBody();
    return checkReturnExpression(tree, resExpr, funcInterfaceMethod, state);
  }
  return Description.NO_MATCH;
}
 
Example 29
Source Project: manifold   Source File: ExtensionTransformer.java    License: Apache License 2.0 5 votes vote down vote up
private void getIncrementalCompileDrivers( JCTree.JCAnnotation anno, Set<Object> drivers )
{
  Attribute.Compound attribute = anno.attribute;
  if( attribute == null )
  {
    return;
  }

  String fqnDriver = null;
  Integer driverId = null;
  for( com.sun.tools.javac.util.Pair<Symbol.MethodSymbol, Attribute> pair: attribute.values )
  {
    Name argName = pair.fst.getSimpleName();
    if( argName.toString().equals( "driverInstance" ) )
    {
      driverId = (int)pair.snd.getValue();
    }
    else if( argName.toString().equals( "driverClass" ) )
    {
      fqnDriver = (String)pair.snd.getValue();
    }
  }

  if( driverId != null )
  {
    Object driver = ReflectUtil.method( fqnDriver, "getInstance", int.class ).invokeStatic( driverId );
    drivers.add( driver );
  }
}
 
Example 30
Source Project: TencentKona-8   Source File: LambdaToMethod.java    License: GNU General Public License v2.0 5 votes vote down vote up
void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) {
        JCClassDecl localCDef = localClassDefs.get(csym);
        if (localCDef != null && lambdaContext.freeVarProcessedLocalClasses.add(csym)) {
            BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() {
                @Override
                void addFreeVars(ClassSymbol c) {
                    captureLocalClassDefs(c, lambdaContext);
                }
                @Override
                void visitSymbol(Symbol sym) {
                    if (sym.kind == VAR &&
                            sym.owner.kind == MTH &&
                            ((VarSymbol)sym).getConstValue() == null) {
                        TranslationContext<?> localContext = context();
                        while (localContext != null) {
                            if (localContext.tree.getTag() == LAMBDA) {
                                JCTree block = capturedDecl(localContext.depth, sym);
                                if (block == null) break;
                                ((LambdaTranslationContext)localContext).addSymbol(sym, CAPTURED_VAR);
                            }
                            localContext = localContext.prev;
                        }
                    }
                }
            };
            fvc.scan(localCDef);
        }
}