Skip to content

Commit

Permalink
Prep for #395: link anonymous type field initializer into JDT model
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Aug 24, 2018
1 parent c90b8ec commit 60185b5
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5922,8 +5922,6 @@ public void testInnerClass1() {
" }\n" +
" public java.lang.Object run() {\n" +
" new Runnable() {\n" +
" public 1() {\n" +
" }\n" +
" public void run() {\n" +
" }\n" +
" };\n" +
Expand All @@ -5950,15 +5948,10 @@ public void testInnerClass1a() {

checkGCUDeclaration("A.groovy",
"public class A {\n" +
" private java.lang.Object foo;\n" +
// " {\n" +
// " new Runnable() {\n" +
// " public 1() {\n" +
// " }\n" +
// " public void run() {\n" +
// " }\n" +
// " };\n" +
// " }\n" +
" private java.lang.Object foo = new Runnable() {\n" +
" public void run() {\n" +
" }\n" +
" };\n" +
" public A() {\n" +
" }\n" +
" public static void main(java.lang.String... args) {\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ private void createTypeDeclarations(ModuleNode moduleNode) {
// record that we need to set the parent of this inner type later
innersToRecord.computeIfAbsent(outerClassNode, x -> new ArrayList<>()).add(typeDeclaration);

if (GroovyUtils.isAnonymous(classNode)) {
if (innerClassNode.isAnonymous()) {
typeDeclaration.bits |= (ASTNode.IsAnonymousType | ASTNode.IsLocalType);
typeDeclaration.bits |= (typeDeclaration.superclass.bits & ASTNode.HasTypeAnnotations);
QualifiedAllocationExpression allocation = new QualifiedAllocationExpression(typeDeclaration);
Expand All @@ -1173,41 +1173,38 @@ private void createTypeDeclarations(ModuleNode moduleNode) {

// now attach local types to their parents; this was not done earlier as sometimes
// the types are processed in such an order that inners are dealt with before outers
for (Map.Entry<ClassNode, List<TypeDeclaration>> innersToRecordEntry : innersToRecord.entrySet()) {
ClassNode outer = innersToRecordEntry.getKey();
TypeDeclaration outerTypeDeclaration = fromClassNodeToDecl.get(outer);
for (Map.Entry<ClassNode, List<TypeDeclaration>> entry : innersToRecord.entrySet()) {
TypeDeclaration outerTypeDeclaration = fromClassNodeToDecl.get(entry.getKey());
if (outerTypeDeclaration == null) {
throw new GroovyEclipseBug("Failed to find the type declaration for " + outer.getText());
throw new GroovyEclipseBug("Failed to find the type declaration for " + entry.getKey().getText());
}

List<TypeDeclaration> newInnersList = innersToRecordEntry.getValue();
for (Iterator<TypeDeclaration> iterator = newInnersList.iterator(); iterator.hasNext();) {
List<TypeDeclaration> memberTypes = entry.getValue();
for (Iterator<TypeDeclaration> iterator = memberTypes.iterator(); iterator.hasNext();) {
GroovyTypeDeclaration innerTypeDeclaration = (GroovyTypeDeclaration) iterator.next();
if ((innerTypeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
iterator.remove();
// set enclosing scope of anon. inner
iterator.remove(); // remove local type from member type list

Object location = anonymousLocations.get(innerTypeDeclaration.getClassNode());
if (location instanceof AbstractMethodDeclaration) {
AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) location;
methodDeclaration.bits |= ASTNode.HasLocalType;

innerTypeDeclaration.enclosingScope = new MethodScope(null, methodDeclaration, methodDeclaration.isStatic());
methodDeclaration.statements = (Statement[]) ArrayUtils.add(methodDeclaration.statements != null
? methodDeclaration.statements : new Statement[0], innerTypeDeclaration.allocation);
? methodDeclaration.statements : new Statement[0], innerTypeDeclaration.allocation);
innerTypeDeclaration.enclosingScope = new MethodScope(null, methodDeclaration, methodDeclaration.isStatic());
} else if (location instanceof FieldDeclaration) {
FieldDeclaration fieldDeclaration = (FieldDeclaration) location;
fieldDeclaration.bits |= ASTNode.HasLocalType;

fieldDeclaration.initialization = innerTypeDeclaration.allocation;
innerTypeDeclaration.enclosingScope = new MethodScope(null, outerTypeDeclaration, fieldDeclaration.isStatic());
// TODO: Add to statements of object/static initializer
} else if (!innerTypeDeclaration.getClassNode().isEnum()) {
throw new GroovyEclipseBug("Enclosing scope not found for anon. inner class: " + innerTypeDeclaration.getClassNode().getName());
}

((GroovyTypeDeclaration) outerTypeDeclaration).addAnonymousType(innerTypeDeclaration);
}
}
outerTypeDeclaration.memberTypes = newInnersList.toArray(new TypeDeclaration[newInnersList.size()]);
outerTypeDeclaration.memberTypes = memberTypes.toArray(new TypeDeclaration[memberTypes.size()]);
}

// clean up
Expand Down Expand Up @@ -1291,19 +1288,17 @@ private void createConstructorDeclarations(ClassNode classNode, boolean isEnum,

List<ConstructorNode> constructorNodes = classNode.getDeclaredConstructors();

char[] ctorName = null;
char[] ctorName; boolean isAnon = false;
if (classNode instanceof InnerClassNode) {
InnerClassNode innerClassNode = (InnerClassNode) classNode;
ClassNode outerClass = innerClassNode.getOuterClass();
String outername = outerClass.getNameWithoutPackage();
String newInner = innerClassNode.getNameWithoutPackage().substring(outername.length() + 1);
ctorName = newInner.toCharArray();
isAnon = ((InnerClassNode) classNode).isAnonymous();
int qualLength = classNode.getOuterClass().getNameWithoutPackage().length() + 1;
ctorName = classNode.getNameWithoutPackage().substring(qualLength).toCharArray();
} else {
ctorName = classNode.getNameWithoutPackage().toCharArray();
}

// add default constructor if no other constructors exist (and not trait/interface)
if (constructorNodes.isEmpty() && !classNode.isInterface() && !isTrait(classNode)) {
// add default constructor if no other constructors exist (and not trait/interface/anonymous)
if (constructorNodes.isEmpty() && !isAnon && !classNode.isInterface() && !isTrait(classNode)) {
ConstructorDeclaration constructor = new ConstructorDeclaration(unitDeclaration.compilationResult);
constructor.bits |= ASTNode.IsDefaultConstructor;
if (isEnum) {
Expand Down Expand Up @@ -1556,7 +1551,7 @@ private org.eclipse.jdt.internal.compiler.ast.Expression createAnnotationMemberE
}
return arrayInitializer;

} else if (expr instanceof AnnotationConstantExpression) {
} else if (expr instanceof AnnotationConstantExpression) {
Annotation[] annos = createAnnotations(Collections.singletonList(
(AnnotationNode) ((AnnotationConstantExpression) expr).getValue()));
assert annos != null && annos.length == 1;
Expand Down

0 comments on commit 60185b5

Please sign in to comment.