use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class BaseTypeVisitor method checkExtendsImplements.
/**
* If "@B class Y extends @A X {}", then enforce that @B must be a subtype of @A.
*
* <p>Also validate the types of the extends and implements clauses.
*
* @param classTree class tree to check
*/
protected void checkExtendsImplements(ClassTree classTree) {
if (TypesUtils.isAnonymous(TreeUtils.typeOf(classTree))) {
// Don't check extends clause on anonymous classes.
return;
}
Set<AnnotationMirror> classBounds = atypeFactory.getTypeDeclarationBounds(TreeUtils.typeOf(classTree));
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
// there is no need to do any subtype checking.
if (classTree.getExtendsClause() != null) {
Set<AnnotationMirror> extendsAnnos = atypeFactory.getTypeOfExtendsImplements(classTree.getExtendsClause()).getAnnotations();
for (AnnotationMirror classAnno : classBounds) {
AnnotationMirror extendsAnno = qualifierHierarchy.findAnnotationInSameHierarchy(extendsAnnos, classAnno);
if (!qualifierHierarchy.isSubtype(classAnno, extendsAnno)) {
checker.reportError(classTree.getExtendsClause(), "declaration.inconsistent.with.extends.clause", classAnno, extendsAnno);
}
}
}
// Do the same check as above for implements clauses.
for (Tree implementsClause : classTree.getImplementsClause()) {
Set<AnnotationMirror> implementsClauseAnnos = atypeFactory.getTypeOfExtendsImplements(implementsClause).getAnnotations();
for (AnnotationMirror classAnno : classBounds) {
AnnotationMirror implementsAnno = qualifierHierarchy.findAnnotationInSameHierarchy(implementsClauseAnnos, classAnno);
if (!qualifierHierarchy.isSubtype(classAnno, implementsAnno)) {
checker.reportError(implementsClause, "declaration.inconsistent.with.implements.clause", classAnno, implementsAnno);
}
}
}
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class JointJavacJavaParserVisitor method visitAnonymousClassBody.
/**
* Visits the the members of an anonymous class body.
*
* <p>In normal classes, javac inserts a synthetic no-argument constructor if no constructor is
* explicitly defined, which is skipped when visiting members. Anonymous class bodies may
* introduce constructors that take arguments if the constructor invocation that created them was
* passed arguments. For example, if {@code MyClass} has a constructor taking a single integer
* argument, then writing {@code new MyClass(5) { }} expands to the javac tree
*
* <pre>{@code
* new MyClass(5) {
* (int arg) {
* super(arg);
* }
* }
* }</pre>
*
* <p>This method skips these synthetic constructors.
*
* @param javacBody body of an anonymous class body
* @param javaParserMembers list of members for the anonymous class body of an {@code
* ObjectCreationExpr}
*/
public void visitAnonymousClassBody(ClassTree javacBody, List<BodyDeclaration<?>> javaParserMembers) {
List<Tree> javacMembers = new ArrayList<>(javacBody.getMembers());
if (!javacMembers.isEmpty()) {
Tree member = javacMembers.get(0);
if (member.getKind() == Tree.Kind.METHOD) {
MethodTree methodTree = (MethodTree) member;
if (methodTree.getName().contentEquals("<init>")) {
javacMembers.remove(0);
}
}
}
visitClassMembers(javacMembers, javaParserMembers);
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class JointJavacJavaParserVisitor method visitClass.
@Override
public Void visitClass(ClassTree javacTree, Node javaParserNode) {
if (javaParserNode instanceof ClassOrInterfaceDeclaration) {
ClassOrInterfaceDeclaration node = (ClassOrInterfaceDeclaration) javaParserNode;
processClass(javacTree, node);
visitLists(javacTree.getTypeParameters(), node.getTypeParameters());
if (javacTree.getKind() == Tree.Kind.CLASS) {
if (javacTree.getExtendsClause() == null) {
assert node.getExtendedTypes().isEmpty();
} else {
assert node.getExtendedTypes().size() == 1;
javacTree.getExtendsClause().accept(this, node.getExtendedTypes().get(0));
}
visitLists(javacTree.getImplementsClause(), node.getImplementedTypes());
} else if (javacTree.getKind() == Tree.Kind.INTERFACE) {
visitLists(javacTree.getImplementsClause(), node.getExtendedTypes());
}
visitClassMembers(javacTree.getMembers(), node.getMembers());
} else if (javaParserNode instanceof RecordDeclaration) {
RecordDeclaration node = (RecordDeclaration) javaParserNode;
processClass(javacTree, node);
visitLists(javacTree.getTypeParameters(), node.getTypeParameters());
visitLists(javacTree.getImplementsClause(), node.getImplementedTypes());
List<? extends Tree> membersWithoutAutoGenerated = Lists.newArrayList(Iterables.filter(javacTree.getMembers(), (Predicate<Tree>) (Tree m) -> {
// Filter out all auto-generated items:
return !TreeUtils.isAutoGeneratedRecordMember(m);
}));
visitClassMembers(membersWithoutAutoGenerated, node.getMembers());
} else if (javaParserNode instanceof AnnotationDeclaration) {
AnnotationDeclaration node = (AnnotationDeclaration) javaParserNode;
processClass(javacTree, node);
visitClassMembers(javacTree.getMembers(), node.getMembers());
} else if (javaParserNode instanceof LocalClassDeclarationStmt) {
javacTree.accept(this, ((LocalClassDeclarationStmt) javaParserNode).getClassDeclaration());
} else if (javaParserNode instanceof LocalRecordDeclarationStmt) {
javacTree.accept(this, ((LocalRecordDeclarationStmt) javaParserNode).getRecordDeclaration());
} else if (javaParserNode instanceof EnumDeclaration) {
EnumDeclaration node = (EnumDeclaration) javaParserNode;
processClass(javacTree, node);
visitLists(javacTree.getImplementsClause(), node.getImplementedTypes());
// members, whereas JavaParser stores them as one object. Need to match them.
assert javacTree.getKind() == Tree.Kind.ENUM;
List<Tree> javacMembers = new ArrayList<>(javacTree.getMembers());
// possibly a synthetic constructor.
if (!node.getEntries().isEmpty()) {
while (!javacMembers.isEmpty() && javacMembers.get(0).getKind() != Tree.Kind.VARIABLE) {
javacMembers.remove(0);
}
}
for (EnumConstantDeclaration entry : node.getEntries()) {
assert !javacMembers.isEmpty();
javacMembers.get(0).accept(this, entry);
javacMembers.remove(0);
}
visitClassMembers(javacMembers, node.getMembers());
} else {
throwUnexpectedNodeType(javacTree, javaParserNode);
}
return null;
}
use of com.sun.source.tree.ClassTree in project checker-framework by typetools.
the class WholeProgramInferenceJavaParserStorage method createWrappersForClass.
/**
* The first two arugments are a javac tree and a JavaParser node representing the same class.
* This method creates wrappers around all the classes, fields, and methods in that class, and
* stores those wrappers in {@code sourceAnnos}.
*
* @param javacClass javac tree for class
* @param javaParserClass JavaParser node corresponding to the same class as {@code javacClass}
* @param sourceAnnos compilation unit wrapper to add new wrappers to
*/
private void createWrappersForClass(ClassTree javacClass, TypeDeclaration<?> javaParserClass, CompilationUnitAnnos sourceAnnos) {
JointJavacJavaParserVisitor visitor = new DefaultJointVisitor() {
@Override
public void processClass(ClassTree javacTree, ClassOrInterfaceDeclaration javaParserNode) {
addClass(javacTree);
}
@Override
public void processClass(ClassTree javacTree, EnumDeclaration javaParserNode) {
addClass(javacTree);
}
@Override
public void processClass(ClassTree javacTree, RecordDeclaration javaParserNode) {
addClass(javacTree);
}
@Override
public void processNewClass(NewClassTree javacTree, ObjectCreationExpr javaParserNode) {
if (javacTree.getClassBody() != null) {
addClass(javacTree.getClassBody());
}
}
/**
* Creates a wrapper around the class for {@code tree} and stores it in {@code
* sourceAnnos}.
*
* @param tree tree to add
*/
private void addClass(ClassTree tree) {
TypeElement classElt = TreeUtils.elementFromDeclaration(tree);
String className = ElementUtils.getBinaryName(classElt);
ClassOrInterfaceAnnos typeWrapper = new ClassOrInterfaceAnnos();
if (!classToAnnos.containsKey(className)) {
classToAnnos.put(className, typeWrapper);
}
sourceAnnos.types.add(typeWrapper);
}
@Override
public void processMethod(MethodTree javacTree, MethodDeclaration javaParserNode) {
addCallableDeclaration(javacTree, javaParserNode);
}
@Override
public void processMethod(MethodTree javacTree, ConstructorDeclaration javaParserNode) {
addCallableDeclaration(javacTree, javaParserNode);
}
/**
* Creates a wrapper around {@code javacTree} with the corresponding declaration {@code
* javaParserNode} and stores it in {@code sourceAnnos}.
*
* @param javacTree javac tree for declaration to add
* @param javaParserNode JavaParser node for the same class as {@code javacTree}
*/
private void addCallableDeclaration(MethodTree javacTree, CallableDeclaration<?> javaParserNode) {
ExecutableElement elt = TreeUtils.elementFromDeclaration(javacTree);
String className = ElementUtils.getEnclosingClassName(elt);
ClassOrInterfaceAnnos enclosingClass = classToAnnos.get(className);
String executableSignature = JVMNames.getJVMMethodSignature(javacTree);
if (!enclosingClass.callableDeclarations.containsKey(executableSignature)) {
enclosingClass.callableDeclarations.put(executableSignature, new CallableDeclarationAnnos(javaParserNode));
}
}
@Override
public void processVariable(VariableTree javacTree, EnumConstantDeclaration javaParserNode) {
VariableElement elt = TreeUtils.elementFromDeclaration(javacTree);
if (!elt.getKind().isField()) {
throw new BugInCF(elt + " is not a field but a " + elt.getKind());
}
String enclosingClassName = ElementUtils.getEnclosingClassName(elt);
ClassOrInterfaceAnnos enclosingClass = classToAnnos.get(enclosingClassName);
String fieldName = javacTree.getName().toString();
enclosingClass.enumConstants.add(fieldName);
// Ensure that if an enum constant defines a class, that class gets registered properly.
// See e.g. https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.1 for
// the specification of an enum constant, which does permit it to define an anonymous
// class.
NewClassTree constructor = (NewClassTree) javacTree.getInitializer();
if (constructor.getClassBody() != null) {
addClass(constructor.getClassBody());
}
}
@Override
public void processVariable(VariableTree javacTree, VariableDeclarator javaParserNode) {
// below call to TreeUtils.elementFromDeclaration causes a crash.
if (TreeUtils.elementFromTree(javacTree) == null) {
return;
}
VariableElement elt = TreeUtils.elementFromDeclaration(javacTree);
if (!elt.getKind().isField()) {
return;
}
String enclosingClassName = ElementUtils.getEnclosingClassName(elt);
ClassOrInterfaceAnnos enclosingClass = classToAnnos.get(enclosingClassName);
String fieldName = javacTree.getName().toString();
if (!enclosingClass.fields.containsKey(fieldName)) {
enclosingClass.fields.put(fieldName, new FieldAnnos(javaParserNode));
}
}
};
visitor.visitClass(javacClass, javaParserClass);
}
use of com.sun.source.tree.ClassTree in project j2objc by google.
the class TreeConverter method convertEnum.
private TreeNode convertEnum(ClassTree node, TreePath parent) {
TreePath path = getTreePath(parent, node);
TypeElement element = (TypeElement) getElement(path);
if (ElementUtil.isAnonymous(element)) {
return convertClassDeclaration(node, parent).setPosition(getPosition(node));
}
EnumDeclaration newNode = new EnumDeclaration();
convertBodyDeclaration(node, parent, node.getModifiers(), newNode);
newNode.setName(convertSimpleName(element, getTypeMirror(path), getNamePosition(node))).setTypeElement(element);
for (Tree bodyDecl : node.getMembers()) {
if (bodyDecl.getKind() == Kind.VARIABLE) {
TreeNode var = convertVariableDeclaration((VariableTree) bodyDecl, path);
if (var.getKind() == TreeNode.Kind.ENUM_CONSTANT_DECLARATION) {
newNode.addEnumConstant((EnumConstantDeclaration) var);
} else {
newNode.addBodyDeclaration((BodyDeclaration) var);
}
} else if (bodyDecl.getKind() == Kind.BLOCK) {
BlockTree javacBlock = (BlockTree) bodyDecl;
Block block = (Block) convert(javacBlock, path);
newNode.addBodyDeclaration(new Initializer(block, javacBlock.isStatic()));
} else {
newNode.addBodyDeclaration((BodyDeclaration) convert(bodyDecl, path));
}
}
return newNode;
}
Aggregations