public Tree visitMemberSelect(MemberSelectTree tree, Object p) { if (tree instanceof QualIdentTree) { QualIdentTree qit = (QualIdentTree) tree; Element el = qit.sym; if (el == null) { el = overlay.resolve(model, elements, qit.getFQN()); } else { if (el.getKind().isClass() || el.getKind().isInterface() || el.getKind() == ElementKind.PACKAGE) { el = overlay.resolve(model, elements, ((QualifiedNameable) el).getQualifiedName().toString(), elements.getModuleOf(el)); } } return importAnalysis.resolveImport(tree, el); } else { return rewriteChildren(tree); } }
private String fqnFor(Tree t) { Element el = ASTService.getElementImpl(t); if (el != null) { if (el.getKind().isClass() || el.getKind().isInterface() || el.getKind() == ElementKind.PACKAGE) { return ((QualifiedNameable) el).getQualifiedName().toString(); } else { Logger.getLogger(ElementOverlay.class.getName()).log(Level.SEVERE, "Not a QualifiedNameable: {0}", el); return null; } } else if (t instanceof QualIdentTree) { return ((QualIdentTree) t).getFQN(); } else if (t.getKind() == Kind.PARAMETERIZED_TYPE) { return fqnFor(((ParameterizedTypeTree) t).getType()); } else { Logger.getLogger(ElementOverlay.class.getName()).log(Level.FINE, "No element and no QualIdent"); return null; } }
private void serialize( Path root, DsvConfiguration configuration, Collection<MethodPartition> partitions, Function<ExecutableElement,QualifiedNameable> keyFunction ) { partitions.forEach( partition -> { String fileSuffix = partition.getFileSuffix(); partition.getMethods().stream().collect( Collectors.groupingBy( keyFunction ) ).entrySet().forEach( kv -> { Either<DsvExportError,List<String>> headerParsingResult = fieldExporter.exportHeaders( configuration.getFieldDelimiter(), configuration.getRawHeaders() ); headerParsingResult.consume( messagePrinter::print, ( headers ) -> { File file = new File( root.toFile(), String.format( "%s%s.csv", kv.getKey().getQualifiedName(), fileSuffix ) ); serializeWithHeaders( file, configuration, kv.getValue(), headers ); } ); } ); } ); }
@Override protected TreeBackedResolvedType resolvePackage( TreePath referencingPath, PackageElement referencedPackage, QualifiedNameable canonicalPackage) { // PackageElements are not considered to be enclosed by their parent elements, but // our logic is a lot simpler if we can pretend they are. TreeBackedResolvedType enclosingElement = null; String qualifiedName = canonicalPackage.getQualifiedName().toString(); int lastDot = qualifiedName.lastIndexOf('.'); if (lastDot > 0) { String enclosingPackageQualifiedName = qualifiedName.substring(0, lastDot); PackageElement enclosingPackage = Preconditions.checkNotNull(elements.getPackageElement(enclosingPackageQualifiedName)); enclosingElement = resolveEnclosingElement(enclosingPackage); } return new TreeBackedResolvedType(referencingPath, canonicalPackage, enclosingElement); }
@Override public void onImport( boolean isStatic, boolean isStarImport, TreePath leafmostElementPath, QualifiedNameable leafmostElement, Name memberName) { if (!isStatic) { if (isStarImport) { starImportedElements.add(leafmostElement); } else { importedTypes.add((TypeElement) leafmostElement); } } else if (!isStarImport) { staticImportOwners.put(memberName.toString(), (TypeElement) leafmostElement); } else { staticStarImports.add((TypeElement) leafmostElement); } }
@Nullable private AnnotationMirror getAnnotationMirror(final Class<? extends Annotation> annotationClass, final Element element) { Optional<? extends AnnotationMirror> annotationMirror = FluentIterable .from(element.getAnnotationMirrors()) .filter(new Predicate<AnnotationMirror>() { @Override public boolean apply(@Nullable AnnotationMirror o) { String qualifiedName = ((QualifiedNameable) (o.getAnnotationType().asElement())).getQualifiedName() .toString(); return qualifiedName.equals(annotationClass.getName()); } } ).first(); if (annotationMirror.isPresent()) { return annotationMirror.get(); } return null; }
private Function<ExecutableElement,QualifiedNameable> groupByFileBasename( DsvGroupingStrategy grouping ) { switch ( grouping ) { case SINGLE: return ( ignored ) -> new ConstantQualifiedNameable( "documentation" ); case PACKAGE: return elements::getPackageOf; case CLASS: return method -> enclosingTypeVisitor.visit( method.getEnclosingElement() ); } throw new IllegalArgumentException( "Unknown grouping strategy: " + grouping ); }
public static boolean isEmulated(QualifiedNameable nameable) { String name = nameable.getQualifiedName().toString(); for(String emul : emuls) { if (name.startsWith(emul)) { return true; } } return false; }
private static String getQualifiedName(Element element) { switch (element.getKind()) { case CLASS: // Mirror API sucks, return proper qualified name for inner classes if (element.getEnclosingElement().getKind() == ElementKind.CLASS) { return getQualifiedName(element.getEnclosingElement()) + '$' + element.getSimpleName(); } else { return ((QualifiedNameable) element).getQualifiedName().toString(); } case METHOD: return getQualifiedName(element.getEnclosingElement()) + ':' + element.getSimpleName().toString(); default: throw new UnsupportedOperationException(element.getClass().toString()); } }
@Override protected TreeBackedResolvedType resolveType( TreePath referencingPath, TypeElement referencedType, QualifiedNameable canonicalType) { if (canonicalType == null) { canonicalType = referencedType; } return new TreeBackedResolvedType( referencingPath, canonicalType, resolveEnclosingElement((QualifiedNameable) canonicalType.getEnclosingElement())); }
private Name getFullyQualifiedName( @Nullable QualifiedNameable enclosingElement, Name simpleName) { for (int i = 0; i < simpleName.length(); i++) { if (simpleName.charAt(i) == '.') { throw new IllegalArgumentException(String.format("%s is not a simple name", simpleName)); } } if (enclosingElement == null || enclosingElement.getQualifiedName().length() == 0) { return simpleName; } else { return getName(String.format("%s.%s", enclosingElement.getQualifiedName(), simpleName)); } }
private static void handleImport(Trees trees, ImportsTracker imports, TreePath importTreePath) { ImportTree importTree = (ImportTree) importTreePath.getLeaf(); MemberSelectTree importedExpression = (MemberSelectTree) importTree.getQualifiedIdentifier(); TreePath importedExpressionPath = new TreePath(importTreePath, importedExpression); Name simpleName = importedExpression.getIdentifier(); boolean isStarImport = simpleName.contentEquals("*"); if (!isStarImport && !importTree.isStatic()) { TypeElement importedType = (TypeElement) trees.getElement(importedExpressionPath); imports.importType(importedType, importedExpressionPath); } else { ExpressionTree containingElementExpression = importedExpression.getExpression(); TreePath containingElementExpressionPath = new TreePath(importedExpressionPath, containingElementExpression); QualifiedNameable containingElement = (QualifiedNameable) trees.getElement(containingElementExpressionPath); if (importTree.isStatic()) { TypeElement containingType = (TypeElement) containingElement; if (isStarImport) { imports.importStaticMembers((TypeElement) containingElement); } else { imports.importStatic(containingType, simpleName); } } else { // Normal star import imports.importMembers(containingElement, containingElementExpressionPath); } } }
public void registerClass(String parent, String clazz, ClassTree tree, boolean modified) { if (clazz == null) return; Element myself = ASTService.getElementImpl(tree); boolean newOrModified = myself == null || (!myself.getKind().isClass() && !myself.getKind().isInterface()) || !((QualifiedNameable) myself).getQualifiedName().contentEquals(clazz); if (newOrModified || class2Enclosed.containsKey(parent)) { List<String> c = class2Enclosed.get(parent); if (c == null) { class2Enclosed.put(parent, c = new ArrayList<String>()); } c.add(clazz); } if (modified) { class2Enclosed.put(clazz, new ArrayList<String>()); } Set<String> superFQNs = superFQNs(tree); boolean hadObject = superFQNs.remove("java.lang.Object"); Set<String> original; if (!newOrModified) { original = new LinkedHashSet<String>(); TypeElement tel = (TypeElement) myself; if (tel.getSuperclass() != null && tel.getSuperclass().getKind() == TypeKind.DECLARED) { original.add(((TypeElement) ((DeclaredType) tel.getSuperclass()).asElement()).getQualifiedName().toString()); } for (TypeMirror intf : tel.getInterfaces()) { original.add(((TypeElement) ((DeclaredType) intf).asElement()).getQualifiedName().toString()); } original.remove("java.lang.Object"); } else { original = null; } if (!superFQNs.equals(original)) { if (hadObject) superFQNs.add("java.lang.Object"); Set<Modifier> mods = EnumSet.noneOf(Modifier.class); mods.addAll(tree.getModifiers().getFlags()); classes.put(clazz, mods); class2SuperElementTrees.put(clazz, superFQNs); } }
@Override public Element getEnclosingElement() { return ElementOverlay.this.resolve(ast, elements, ((QualifiedNameable/*XXX*/) delegateTo.getEnclosingElement()).getQualifiedName().toString(), moduleOf(elements, delegateTo)); }
protected CompiledPropertyMetadata toPropertyMetadata(VariableElement element, AnnotationMirror propertyAnnotation) { Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues = processingEnv.getElementUtils().getElementValuesWithDefaults(propertyAnnotation); CompiledPropertyMetadata property = new CompiledPropertyMetadata(); String propName = (String) annotationValue(annotationValues, "name").getValue(); if (propName == null || propName.isEmpty()) { propName = (String) element.getConstantValue(); if (propName == null) { processingEnv.getMessager().printMessage(Kind.WARNING, "Failed to read constant value for " + element, element); return null; } } property.setName(propName); boolean deprecated = processingEnv.getElementUtils().isDeprecated(element); property.setDeprecated(deprecated); QualifiedNameable enclosingElement = (QualifiedNameable) element.getEnclosingElement(); property.setConstantDeclarationClass(enclosingElement.getQualifiedName().toString()); property.setConstantFieldName(element.getSimpleName().toString()); property.setCategory((String) annotationValue(annotationValues, "category").getValue()); property.setDefaultValue((String) annotationValue(annotationValues, "defaultValue").getValue()); property.setSinceVersion((String) annotationValue(annotationValues, "sinceVersion").getValue()); property.setValueType(((TypeMirror) annotationValue(annotationValues, "valueType").getValue()).toString()); @SuppressWarnings("unchecked") List<? extends AnnotationValue> scopeValues = (List<? extends AnnotationValue>) annotationValue(annotationValues, "scopes").getValue(); List<PropertyScope> propertyScopes = new ArrayList<>(scopeValues.size()); for (AnnotationValue scopeValue : scopeValues) { PropertyScope scope = Enum.valueOf(PropertyScope.class, ((VariableElement) scopeValue.getValue()).getSimpleName().toString()); propertyScopes.add(scope); } //automatically adding Global if Context is present int contextIndex = propertyScopes.indexOf(PropertyScope.CONTEXT); if (contextIndex >= 0 && !propertyScopes.contains(PropertyScope.GLOBAL)) { propertyScopes.add(contextIndex, PropertyScope.GLOBAL); } property.setScopes(propertyScopes); @SuppressWarnings("unchecked") List<? extends AnnotationValue> scopeQualificationValues = (List<? extends AnnotationValue>) annotationValue(annotationValues, "scopeQualifications").getValue(); List<String> scopeQualifications = new ArrayList<>(scopeValues.size()); for (AnnotationValue qualificationValue : scopeQualificationValues) { String qualification = (String) qualificationValue.getValue(); scopeQualifications.add(qualification); } property.setScopeQualifications(scopeQualifications); return property; }
@Override public void onImport( boolean isStatic, boolean isStarImport, TreePath leafmostElementPath, QualifiedNameable leafmostElement, @Nullable Name memberName) { if (leafmostElement.getKind() != ElementKind.PACKAGE) { if (isStatic) { CompletedType completedType = completer.complete(leafmostElement, true); if (completedType != null && (completedType.kind == CompletedTypeKind.CRASH || completedType.kind == CompletedTypeKind.PARTIALLY_COMPLETED_TYPE)) { reportMissingDeps(completedType, leafmostElementPath); } } else { ResolvedType compilerResolvedType = compilerResolver.resolve(leafmostElementPath); if (compilerResolvedType != null && compilerResolvedType.kind == ResolvedTypeKind.CRASH) { reportMissingDeps(compilerResolvedType, leafmostElementPath); } else { TreeBackedResolvedType treeBackedResolvedType = treeBackedResolver.resolve(leafmostElementPath); if (!treeBackedResolvedType.isCorrect()) { if (treeBackedResolvedType.isCorrectable()) { treeBackedResolvedType.reportErrors(messageKind); } else { reportMissingDeps(compilerResolvedType, leafmostElementPath); } } } } } if (!isStatic) { if (!isStarImport) { imports.importType((TypeElement) leafmostElement, leafmostElementPath); } else { imports.importMembers(leafmostElement, leafmostElementPath); } } else if (!isStarImport) { imports.importStatic((TypeElement) leafmostElement, Preconditions.checkNotNull(memberName)); } else { imports.importStaticMembers((TypeElement) leafmostElement); } }
public void importMembers(QualifiedNameable typeOrPackage, @Nullable TreePath location) { importedOwners.put(typeOrPackage, location); }
/** * Serializes processed extensions according to the input configuration. * The actual write operations are handled by {@link DsvFileWriter}. * <p> * The main added value of this indirection is to properly reorganize the data * so it complies to the user configuration, may it be in terms of grouping strategies * (see {@link DsvGroupingStrategy}), splitting strategy (see {@link DsvSplitStrategy}), * custom field delimiter and/or exported header selection. * <p> * All of these combinable settings are specified by {@link DsvConfiguration}, based on * the options passed to the annotation processor {@link DsvProcessor}. * * @param root root folder that is going to contain the generated files * @param configuration file grouping/item splitting options, exported headers * @param procedures processed user-defined procedures * @param functions processed user-defined functions */ public void serialize( Path root, DsvConfiguration configuration, Collection<ExecutableElement> procedures, Collection<ExecutableElement> functions ) { DsvSplitStrategy splitStrategy = configuration.getSplitStrategy(); configuration.getGroupingStrategies().forEach( grouping -> { Collection<MethodPartition> partitions = splitStrategy.partition( procedures, functions ); Function<ExecutableElement,QualifiedNameable> keyFunction = groupByFileBasename( grouping ); serialize( root, configuration, partitions, keyFunction ); } ); }
/** * An import statement was encountered. * * @param isStatic true for static imports * @param isStarImport true for star imports * @param leafmostElementPath the path of the leafmost known element in the imported type * expression * @param leafmostElement the leafmost known element in the imported type expression. For * single-type imports, this is the imported type. For the rest, this is the type or package * enclosing the imported element(s). * @param memberName for named static imports, the name of the static members to import. * Otherwise null. */ void onImport( boolean isStatic, boolean isStarImport, TreePath leafmostElementPath, QualifiedNameable leafmostElement, @Nullable Name memberName);