@Override protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) { if (clazz.type.hasTag(TypeTag.UNKNOWN)) { return; } ClassDocImpl result = classMap.get(clazz); if (result != null) { if (treePath != null) setTreePath(result, treePath); return; } if (isAnnotationType((JCClassDecl)treePath.getLeaf())) { // flags of clazz may not yet be set result = new JavadocAnnotation(this, clazz, treePath); } else { result = new JavadocClass(this, clazz, treePath); } classMap.put(clazz, result); }
@Override public void visitClassDef(JCClassDecl tree) { TypeSymbol currentClassPrev = currentClass; currentClass = tree.sym; List<Pair<TypeSymbol, Symbol>> prevOuterThisStack = outerThisStack; try { if (currentClass != null) { if (currentClass.hasOuterInstance()) outerThisDef(currentClass); super.visitClassDef(tree); } } finally { outerThisStack = prevOuterThisStack; currentClass = currentClassPrev; } }
public void test223701() throws Exception { File testFile = new File(work, "Test.java"); final String origin = "/*a*/\npackage test;\n" + "class Test {\n" + "}"; TestUtilities.copyStringToFile(testFile, origin); JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws Exception { workingCopy.toPhase(JavaSource.Phase.PARSED); ClassTree ct = (ClassTree) workingCopy.getCompilationUnit().getTypeDecls().get(0); ((JCClassDecl) ct).pos = 1;//"great" positions apparently produced by some code-generating tools (read: Lombok) GeneratorUtilities.get(workingCopy).importComments(ct, workingCopy.getCompilationUnit()); } }; src.runModificationTask(task); }
private void dumpSymFile( @NonNull final JavaFileManager jfm, @NonNull final JavacTaskImpl jti, @NullAllowed final ClassSymbol cs, @NonNull final Set<File> alreadyCreated, @NonNull final File classes, @NonNull final HashMap<ClassSymbol, JCClassDecl> syms2trees) throws IOException { if (cs == null) { //ClassDecl has no symbol because compilation was cancelled //by low memory before ENTER done. return; } JavaFileObject file = jfm.getJavaFileForOutput(StandardLocation.CLASS_OUTPUT, cs.flatname.toString(), JavaFileObject.Kind.CLASS, cs.sourcefile); if (file instanceof FileObjects.FileBase && !alreadyCreated.contains(((FileObjects.FileBase)file).getFile())) { TreeLoader.dumpSymFile(jfm, jti, cs, classes, syms2trees); } }
/** * Emit plain Java source for a class. * * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); return null; } else { BufferedWriter out = new BufferedWriter(outFile.openWriter()); try { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) log.printVerbose("wrote.file", outFile); } finally { out.close(); } return outFile; } }
/** Emit plain Java source for a class. * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), Errors.SourceCantOverwriteInputFile(outFile)); return null; } else { try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) log.printVerbose("wrote.file", outFile); } return outFile; } }
@Override @DefinedBy(Api.COMPILER_TREE) public Symbol getElement(TreePath path) { JCTree tree = (JCTree) path.getLeaf(); Symbol sym = TreeInfo.symbolFor(tree); if (sym == null) { for (TreePath p = path; p != null; p = p.getParentPath()) { JCTree t = (JCTree) p.getLeaf(); if (t.hasTag(JCTree.Tag.CLASSDEF)) { JCClassDecl ct = (JCClassDecl) t; if (ct.sym != null) { if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { attr.attribClass(ct.pos(), ct.sym); sym = TreeInfo.symbolFor(tree); } break; } } } } return sym; }
private void handleFlowResults(Queue<Env<AttrContext>> queue, ListBuffer<Element> elems) { for (Env<AttrContext> env: queue) { switch (env.tree.getTag()) { case CLASSDEF: JCClassDecl cdef = (JCClassDecl) env.tree; if (cdef.sym != null) elems.append(cdef.sym); break; case MODULEDEF: JCModuleDecl mod = (JCModuleDecl) env.tree; if (mod.sym != null) elems.append(mod.sym); break; case PACKAGEDEF: JCCompilationUnit unit = env.toplevel; if (unit.packge != null) elems.append(unit.packge); break; } } genList.addAll(queue); }
@Override public void visitClassDef(JCClassDecl tree) { if ((tree.mods.flags & (INTERFACE | ENUM)) == 0 && !tree.getMembers().stream() .anyMatch(t -> t.getKind() == Tree.Kind.METHOD && ((MethodTree) t).getName() == tree.name.table.names.init)) { // Generate a default constructor, since // this is a regular class and there are no constructors ListBuffer<JCTree> ndefs = new ListBuffer<>(); ndefs.addAll(tree.defs); ndefs.add(make.MethodDef(make.Modifiers(PUBLIC), tree.name.table.names.init, null, List.nil(), List.nil(), List.nil(), resolutionExceptionBlock(), null)); tree.defs = ndefs.toList(); } super.visitClassDef(tree); }
/** Emit plain Java source for a class. * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); return null; } else { try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) log.printVerbose("wrote.file", outFile); } return outFile; } }
@Override @DefinedBy(Api.COMPILER_TREE) public Symbol getElement(TreePath path) { JCTree tree = (JCTree) path.getLeaf(); Symbol sym = TreeInfo.symbolFor(tree); if (sym == null) { if (TreeInfo.isDeclaration(tree)) { for (TreePath p = path; p != null; p = p.getParentPath()) { JCTree t = (JCTree) p.getLeaf(); if (t.hasTag(JCTree.Tag.CLASSDEF)) { JCClassDecl ct = (JCClassDecl) t; if (ct.sym != null) { if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { attr.attribClass(ct.pos(), ct.sym); sym = TreeInfo.symbolFor(tree); } break; } } } } } return sym; }
@Override public void process(Element element) { if (element instanceof TypeElement) { String qualifiedName = ((TypeElement)element).getQualifiedName().toString(); String exclusionRule = getExclusionRule(qualifiedName); if (exclusionRule != null) { Logger.note(getClass(), "process", "not instrumenting class '" + qualifiedName + "', '"+exclusionRule+"' is excluded"); return; } } JCClassDecl klass = toJCClassDecl(element); final String className = klass.getSimpleName().toString(); Logger.note(getClass(), "process", "instrumenting class: " + className); // NOTE(snorbi07): IMPORTANT: this only does the processing of TOP LEVEL classes (class source files)! // Inner classes are part of the parent classes source tree and processed as such. processClass(klass); }
protected JCClassDecl toJCClassDecl(Element element) { /* * Cast the JSR269 tree node to its compiler internal type. The * difference between JSR269 tree nodes and internal tree node is, that * JSR269 stops at method level, whereas internally all AST elements are * accessible. We need full access in order to inject entering/leaving * statements. */ JCTree tree = (JCTree) trees.getTree(element); if (!(tree instanceof JCClassDecl)) { throw new IllegalArgumentException("Expected type: " + JCClassDecl.class.getSimpleName() + ". Got: " + Element.class.getSimpleName()); } JCClassDecl klass = (JCClassDecl) tree; return klass; }
/** {@inheritDoc} */ @Override protected JavacNode buildTree(JCTree node, Kind kind) { switch (kind) { case COMPILATION_UNIT: return buildCompilationUnit((JCCompilationUnit) node); case TYPE: return buildType((JCClassDecl) node); case FIELD: return buildField((JCVariableDecl) node); case INITIALIZER: return buildInitializer((JCBlock) node); case METHOD: return buildMethod((JCMethodDecl) node); case ARGUMENT: return buildLocalVar((JCVariableDecl) node, kind); case LOCAL: return buildLocalVar((JCVariableDecl) node, kind); case STATEMENT: return buildStatementOrExpression(node); case ANNOTATION: return buildAnnotation((JCAnnotation) node, false); default: throw new AssertionError("Did not expect: " + kind); } }
private JavacNode buildType(JCClassDecl type) { if (setAndGetAsHandled(type)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); for (JCAnnotation annotation : type.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation, false)); for (JCTree def : type.defs) { /* A def can be: * JCClassDecl for inner types * JCMethodDecl for constructors and methods * JCVariableDecl for fields * JCBlock for (static) initializers */ if (def instanceof JCMethodDecl) addIfNotNull(childNodes, buildMethod((JCMethodDecl)def)); else if (def instanceof JCClassDecl) addIfNotNull(childNodes, buildType((JCClassDecl)def)); else if (def instanceof JCVariableDecl) addIfNotNull(childNodes, buildField((JCVariableDecl)def)); else if (def instanceof JCBlock) addIfNotNull(childNodes, buildInitializer((JCBlock)def)); } return putInMap(new JavacNode(this, type, childNodes, Kind.TYPE)); }
public static JCExpression cloneSelfType(JavacNode childOfType) { JavacNode typeNode = childOfType; JavacTreeMaker maker = childOfType.getTreeMaker(); while (typeNode != null && typeNode.getKind() != Kind.TYPE) typeNode = typeNode.up(); if (typeNode != null && typeNode.get() instanceof JCClassDecl) { JCClassDecl type = (JCClassDecl) typeNode.get(); ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>(); if (!type.typarams.isEmpty()) { for (JCTypeParameter tp : type.typarams) { typeArgs.append(maker.Ident(tp.name)); } return maker.TypeApply(maker.Ident(type.name), typeArgs.toList()); } else { return maker.Ident(type.name); } } else { return null; } }
/** * Checks if there is a field with the provided name. * * @param fieldName the field name to check for. * @param node Any node that represents the Type (JCClassDecl) to look in, or any child node thereof. */ public static MemberExistsResult fieldExists(String fieldName, JavacNode node) { node = upToTypeNode(node); if (node != null && node.get() instanceof JCClassDecl) { for (JCTree def : ((JCClassDecl)node.get()).defs) { if (def instanceof JCVariableDecl) { if (((JCVariableDecl)def).name.contentEquals(fieldName)) { return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } } return MemberExistsResult.NOT_EXISTS; }
/** * Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only * the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned. * * @param node Any node that represents the Type (JCClassDecl) to look in, or any child node thereof. */ public static MemberExistsResult constructorExists(JavacNode node) { node = upToTypeNode(node); if (node != null && node.get() instanceof JCClassDecl) { top: for (JCTree def : ((JCClassDecl)node.get()).defs) { if (def instanceof JCMethodDecl) { JCMethodDecl md = (JCMethodDecl) def; if (md.name.contentEquals("<init>")) { if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue; List<JCAnnotation> annotations = md.getModifiers().getAnnotations(); if (annotations != null) for (JCAnnotation anno : annotations) { if (typeMatches(Tolerate.class, node, anno.getAnnotationType())) continue top; } return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } } return MemberExistsResult.NOT_EXISTS; }
private List<Fix> fixesFromFields(VisitorState state, final ExpressionTree receiver) { FluentIterable<JCVariableDecl> collectionFields = FluentIterable.from( ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class).getMembers()) .filter(JCVariableDecl.class) .filter(isCollectionVariable(state)); Multimap<Integer, JCVariableDecl> potentialReplacements = partitionByEditDistance(simpleNameOfIdentifierOrMemberAccess(receiver), collectionFields); return buildValidReplacements( potentialReplacements, new Function<JCVariableDecl, Fix>() { @Override public Fix apply(JCVariableDecl var) { return SuggestedFix.replace(receiver, "this." + var.sym.toString()); } }); }
/** * Performs a best-effort search for the AST node of a field declaration. * * <p>It will only find fields declared in a lexically enclosing scope of the current location. * Since double-checked locking should always be used on a private field, this should be * reasonably effective. */ @Nullable private static JCTree findFieldDeclaration(TreePath path, VarSymbol var) { for (TreePath curr = path; curr != null; curr = curr.getParentPath()) { Tree leaf = curr.getLeaf(); if (!(leaf instanceof JCClassDecl)) { continue; } for (JCTree tree : ((JCClassDecl) leaf).getMembers()) { if (Objects.equals(var, ASTHelpers.getSymbol(tree))) { return tree; } } } return null; }
@Override public Description matchMethod(MethodTree method, VisitorState state) { if (!CAN_BE_A_MULTIBINDS_METHOD.matches(method, state)) { return NO_MATCH; } JCClassDecl enclosingClass = ASTHelpers.findEnclosingNode(state.getPath(), JCClassDecl.class); // Check to see if this is in a Dagger 1 module b/c it doesn't support @Multibinds for (JCAnnotation annotation : enclosingClass.getModifiers().getAnnotations()) { if (ASTHelpers.getSymbol(annotation.getAnnotationType()) .getQualifiedName() .contentEquals("dagger.Module") && HAS_DAGGER_ONE_MODULE_ARGUMENT.matches(annotation, state)) { return NO_MATCH; } } return fixByModifyingMethod(state, enclosingClass, method); }
private Description fixByModifyingMethod( VisitorState state, JCClassDecl enclosingClass, MethodTree method) { JCModifiers methodModifiers = ((JCMethodDecl) method).getModifiers(); String replacementModifiersString = createReplacementMethodModifiers(state, methodModifiers); JCModifiers enclosingClassModifiers = enclosingClass.getModifiers(); String enclosingClassReplacementModifiersString = createReplacementClassModifiers(state, enclosingClassModifiers); SuggestedFix.Builder fixBuilder = SuggestedFix.builder() .addImport("dagger.multibindings.Multibinds") .replace(methodModifiers, replacementModifiersString) .replace(method.getBody(), ";"); fixBuilder = (enclosingClassModifiers.pos == -1) ? fixBuilder.prefixWith(enclosingClass, enclosingClassReplacementModifiersString) : fixBuilder.replace(enclosingClassModifiers, enclosingClassReplacementModifiersString); return describeMatch(method, fixBuilder.build()); }
public JCMethodDecl reifyMethodDeclaration(String methodDeclaration) { String wrappedMethodDeclaration = wrapMethodDeclaration(methodDeclaration); JavacParser parser = getParserForString(wrappedMethodDeclaration); JCCompilationUnit compilationUnit = parser.parseCompilationUnit(); JCTree classDefinition = compilationUnit.defs.head; if (classDefinition instanceof JCClassDecl) { JCClassDecl classDeclaration = (JCClassDecl) classDefinition; JCTree firstClassHeadDefinition = classDeclaration.defs.head; if (firstClassHeadDefinition instanceof JCMethodDecl) { return (JCMethodDecl) firstClassHeadDefinition; } // tbd: checked exception handling throw new RuntimeException("The first definition in the class declaration is not a method declaration"); } // tbd: checked exception handling throw new RuntimeException("The first definition in the compilation unit is not a class declaration."); }
/** ClassCreatorRest = Arguments [ClassBody] */ JCNewClass classCreatorRest(int newpos, JCExpression encl, List<JCExpression> typeArgs, JCExpression t) { List<JCExpression> args = arguments(); JCClassDecl body = null; if (S.token() == LBRACE) { int pos = S.pos(); List<JCTree> defs = classOrInterfaceBody(names.empty, false); JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); body = toP(F.at(pos).AnonymousClassDef(mods, defs)); } return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); }
/** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] * [IMPLEMENTS TypeList] ClassBody * @param mods The modifiers starting the class declaration * @param dc The documentation comment for the class, or null. */ JCClassDecl classDeclaration(JCModifiers mods, String dc) { int pos = S.pos(); accept(CLASS); Name name = ident(); List<JCTypeParameter> typarams = typeParametersOpt(); JCExpression extending = null; if (S.token() == EXTENDS) { S.nextToken(); extending = parseType(); } List<JCExpression> implementing = List.nil(); if (S.token() == IMPLEMENTS) { S.nextToken(); implementing = typeList(); } List<JCTree> defs = classOrInterfaceBody(name, false); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, extending, implementing, defs)); attach(result, dc); return result; }
/** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt * [EXTENDS TypeList] InterfaceBody * @param mods The modifiers starting the interface declaration * @param dc The documentation comment for the interface, or null. */ JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { int pos = S.pos(); accept(INTERFACE); Name name = ident(); List<JCTypeParameter> typarams = typeParametersOpt(); List<JCExpression> extending = List.nil(); if (S.token() == EXTENDS) { S.nextToken(); extending = typeList(); } List<JCTree> defs = classOrInterfaceBody(name, true); JCClassDecl result = toP(F.at(pos).ClassDef( mods, name, typarams, null, extending, defs)); attach(result, dc); return result; }
/** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody * @param mods The modifiers starting the enum declaration * @param dc The documentation comment for the enum, or null. */ JCClassDecl enumDeclaration(JCModifiers mods, String dc) { int pos = S.pos(); accept(ENUM); Name name = ident(); List<JCExpression> implementing = List.nil(); if (S.token() == IMPLEMENTS) { S.nextToken(); implementing = typeList(); } List<JCTree> defs = enumBody(name); mods.flags |= Flags.ENUM; JCClassDecl result = toP(F.at(pos). ClassDef(mods, name, List.<JCTypeParameter>nil(), null, implementing, defs)); attach(result, dc); return result; }
/** * Emit plain Java source for a class. * * @param env * The attribution environment of the outermost class containing * this class. * @param cdef * The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); return null; } else { BufferedWriter out = new BufferedWriter(outFile.openWriter()); try { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) log.printVerbose("wrote.file", outFile); } finally { out.close(); } return outFile; } }
private void recordInfo(JCCompilationUnit toplevel) { CompilationUnit.Builder builder = CompilationUnit.newBuilder(); if (toplevel.sourcefile != null) { // FileObject#getName() returns the original exec root-relative path of // the source file, which is want we want. // Paths.get(sourcefile.toUri()) would absolutize the path. Path path = Paths.get(toplevel.sourcefile.getName()); builder.setPath(processingModule.stripSourceRoot(path).toString()); builder.setGeneratedByAnnotationProcessor(processingModule.isGenerated(path)); } if (toplevel.getPackageName() != null) { builder.setPkg(toplevel.getPackageName().toString()); } for (JCTree decl : toplevel.defs) { if (decl instanceof JCClassDecl) { builder.addTopLevel(((JCClassDecl) decl).getSimpleName().toString()); } } processingModule.recordUnit(builder.build()); }
public static JavacNode findMethod(String methodName, JavacNode node) { while (node != null && !(node.get() instanceof JCTree.JCClassDecl)) { node = node.up(); } if (node != null && node.get() instanceof JCTree.JCClassDecl) { for (JCTree def : ((JCTree.JCClassDecl) node.get()).defs) { if (def instanceof JCTree.JCMethodDecl) { String name = ((JCTree.JCMethodDecl) def).name.toString(); if (name.equals(methodName)) { return node.getNodeFor(def); } } } } return null; }
public static JavacNode getField(JavacNode node, String fieldName) { while (node != null && !(node.get() instanceof JCTree.JCClassDecl)) { node = node.up(); } if (node != null && node.get() instanceof JCTree.JCClassDecl) { for (JCTree def : ((JCTree.JCClassDecl) node.get()).defs) { if (def instanceof JCTree.JCVariableDecl) { if (((JCTree.JCVariableDecl) def).name.contentEquals(fieldName)) { return node.getNodeFor(def); } } } } return null; }
public static JCTree.JCExpression readField(JavacNode fieldNode, JCTree.JCExpression receiver) { TreeMaker maker = fieldNode.getTreeMaker(); JCTree.JCVariableDecl fieldDecl = (JCTree.JCVariableDecl) fieldNode.get(); if (receiver == null) { if ((fieldDecl.mods.flags & Flags.STATIC) == 0) { receiver = maker.Ident(fieldNode.toName("this")); } else { JavacNode containerNode = fieldNode.up(); if (containerNode != null && containerNode.get() instanceof JCTree.JCClassDecl) { JCTree.JCClassDecl container = (JCTree.JCClassDecl) fieldNode.up().get(); receiver = maker.Ident(container.name); } } } return receiver == null ? maker.Ident(fieldDecl.name) : maker.Select(receiver, fieldDecl.name); }
public IStreamedFragment<EObject, Annotation> getFragment(JCCompilationUnit cu) { IStreamedFragment<EObject, Annotation> fragment = createNewFragment(); // JCCompilationUnit cu = parse(file); EJCCompilationUnit cu_t = createObject(fragment, EJCCompilationUnit.class); // EjctreeFactory.eINSTANCE.createEJCCompilationUnit(); cu_t.setSourceFile( cu.getSourceFile().getName() ); List<JCTree> types = cu.getTypeDecls(); for (JCTree clazzTree : types) { if ( clazzTree instanceof JCClassDecl) { JCClassDecl clazz = (JCClassDecl) clazzTree; cu_t.getTypeDecls().add( mapClass(fragment, cu, clazz) ); } } return fragment; }