use of com.github.javaparser.ast.body.RecordDeclaration in project checker-framework by typetools.
the class DoubleJavaParserVisitor method visit.
@Override
public void visit(RecordDeclaration node1, Node other) {
RecordDeclaration node2 = (RecordDeclaration) other;
defaultAction(node1, node2);
visitLists(node1.getImplementedTypes(), node2.getImplementedTypes());
visitLists(node1.getTypeParameters(), node2.getTypeParameters());
visitLists(node1.getParameters(), node2.getParameters());
visitLists(node1.getMembers(), node2.getMembers());
visitLists(node1.getModifiers(), node2.getModifiers());
node1.getName().accept(this, node2.getName());
if (node1.getReceiverParameter().isPresent() && node2.getReceiverParameter().isPresent()) {
node1.getReceiverParameter().get().accept(this, node2.getReceiverParameter().get());
}
}
use of com.github.javaparser.ast.body.RecordDeclaration in project checker-framework by typetools.
the class AnnotationFileParser method processTypeDecl.
/**
* Process a type declaration: copy its annotations to {@code #annotationFileAnnos}.
*
* <p>This method stores the declaration's type parameters in {@link #typeParameters}. When
* processing an ajava file, where traversal is handled externaly by a {@link
* org.checkerframework.framework.ajava.JointJavacJavaParserVisitor}, these type variables must be
* removed after processing the type's members. Otherwise, this method removes them.
*
* @param typeDecl the type declaration to process
* @param outertypeName the name of the containing class, when processing a nested class;
* otherwise null
* @param classTree the tree corresponding to typeDecl if processing an ajava file, null otherwise
* @return a list of types variables for {@code typeDecl}. Only non-null if processing an ajava
* file, in which case the contents should be removed from {@link #typeParameters} after
* processing the type declaration's members
*/
private List<AnnotatedTypeVariable> processTypeDecl(TypeDeclaration<?> typeDecl, String outertypeName, @Nullable ClassTree classTree) {
assert typeBeingParsed != null;
if (skipNode(typeDecl)) {
return null;
}
String innerName;
@FullyQualifiedName String fqTypeName;
TypeElement typeElt;
if (classTree != null) {
typeElt = TreeUtils.elementFromDeclaration(classTree);
innerName = typeElt.getQualifiedName().toString();
typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
fqTypeName = typeBeingParsed.toString();
} else {
String packagePrefix = outertypeName == null ? "" : outertypeName + ".";
innerName = packagePrefix + typeDecl.getNameAsString();
typeBeingParsed = new FqName(typeBeingParsed.packageName, innerName);
fqTypeName = typeBeingParsed.toString();
typeElt = elements.getTypeElement(fqTypeName);
}
if (!isAnnotatedForThisChecker(typeDecl.getAnnotations())) {
return null;
}
if (typeElt == null) {
if (debugAnnotationFileParser || (!warnIfNotFoundIgnoresClasses && !hasNoAnnotationFileParserWarning(typeDecl.getAnnotations()) && !hasNoAnnotationFileParserWarning(packageAnnos))) {
if (elements.getAllTypeElements(fqTypeName).isEmpty()) {
stubWarnNotFound(typeDecl, "Type not found: " + fqTypeName);
} else {
stubWarnNotFound(typeDecl, "Type not found uniquely: " + fqTypeName + " : " + elements.getAllTypeElements(fqTypeName));
}
}
return null;
}
List<AnnotatedTypeVariable> typeDeclTypeParameters = null;
if (typeElt.getKind() == ElementKind.ENUM) {
if (!(typeDecl instanceof EnumDeclaration)) {
warn(typeDecl, innerName + " is an enum, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
typeDeclTypeParameters = processEnum((EnumDeclaration) typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
} else if (typeElt.getKind() == ElementKind.ANNOTATION_TYPE) {
if (!(typeDecl instanceof AnnotationDeclaration)) {
warn(typeDecl, innerName + " is an annotation, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
stubWarnNotFound(typeDecl, "Skipping annotation type: " + fqTypeName);
} else if (typeDecl instanceof ClassOrInterfaceDeclaration) {
if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
warn(typeDecl, innerName + " is a class or interface, but stub file declared it as " + typeDecl.toString().split("\\R", 2)[0] + "...");
return null;
}
typeDeclTypeParameters = processType(typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
} else if (typeDecl instanceof RecordDeclaration) {
typeDeclTypeParameters = processType(typeDecl, typeElt);
typeParameters.addAll(typeDeclTypeParameters);
}
// of this method.
if (fileType == AnnotationFileType.AJAVA) {
return typeDeclTypeParameters;
}
if (typeDecl instanceof RecordDeclaration) {
NodeList<Parameter> recordMembers = ((RecordDeclaration) typeDecl).getParameters();
LinkedHashMap<String, RecordComponentStub> byName = new LinkedHashMap<>();
for (Parameter recordMember : recordMembers) {
RecordComponentStub stub = processRecordField(recordMember, findFieldElement(typeElt, recordMember.getNameAsString(), recordMember));
byName.put(recordMember.getNameAsString(), stub);
}
annotationFileAnnos.records.put(typeDecl.getFullyQualifiedName().get(), new RecordStub(byName));
}
Pair<Map<Element, BodyDeclaration<?>>, Map<Element, List<BodyDeclaration<?>>>> members = getMembers(typeDecl, typeElt, typeDecl);
for (Map.Entry<Element, BodyDeclaration<?>> entry : members.first.entrySet()) {
final Element elt = entry.getKey();
final BodyDeclaration<?> decl = entry.getValue();
switch(elt.getKind()) {
case FIELD:
processField((FieldDeclaration) decl, (VariableElement) elt);
break;
case ENUM_CONSTANT:
// the TRACKER enum constant annotated with DefaultType:
if (decl instanceof FieldDeclaration) {
processField((FieldDeclaration) decl, (VariableElement) elt);
} else if (decl instanceof EnumConstantDeclaration) {
processEnumConstant((EnumConstantDeclaration) decl, (VariableElement) elt);
} else {
throw new BugInCF("Unexpected decl type " + decl.getClass() + " for ENUM_CONSTANT kind, original: " + decl);
}
break;
case CONSTRUCTOR:
case METHOD:
processCallableDeclaration((CallableDeclaration<?>) decl, (ExecutableElement) elt);
break;
case CLASS:
case INTERFACE:
// Not processing an ajava file, so ignore the return value.
processTypeDecl((ClassOrInterfaceDeclaration) decl, innerName, null);
break;
case ENUM:
// Not processing an ajava file, so ignore the return value.
processTypeDecl((EnumDeclaration) decl, innerName, null);
break;
default:
/* do nothing */
stubWarnNotFound(decl, "AnnotationFileParser ignoring: " + elt);
break;
}
}
for (Map.Entry<Element, List<BodyDeclaration<?>>> entry : members.second.entrySet()) {
ExecutableElement fakeOverridden = (ExecutableElement) entry.getKey();
List<BodyDeclaration<?>> fakeOverrideDecls = entry.getValue();
for (BodyDeclaration<?> bodyDecl : fakeOverrideDecls) {
processFakeOverride(fakeOverridden, (CallableDeclaration<?>) bodyDecl, typeElt);
}
}
if (typeDeclTypeParameters != null) {
typeParameters.removeAll(typeDeclTypeParameters);
}
return null;
}
use of com.github.javaparser.ast.body.RecordDeclaration 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.github.javaparser.ast.body.RecordDeclaration 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);
}
Aggregations