/*
* Copyright 2009-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.jdt.groovy.internal.compiler.ast;
import java.util.List;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.PropertyNode;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.parser.Parser;
public class GroovyTypeDeclaration extends TypeDeclaration {
public List<PropertyNode> properties;
// The Groovy ClassNode that gave rise to this type declaration
private ClassNode classNode;
public GroovyTypeDeclaration(CompilationResult compilationResult, ClassNode classNode) {
super(compilationResult);
this.classNode = classNode;
}
public ClassNode getClassNode() {
return classNode;
}
// FIXASC Is this always what we want to do - are there any other implications?
@Override
public void parseMethods(Parser parser, CompilationUnitDeclaration unit) {
// prevent Groovy types from having their methods re-parsed
// if (parser instanceof MultiplexingCommentRecorderParser) {
// super.parseMethods(parser, unit);
// }
}
@Override
public boolean isScannerUsableOnThisDeclaration() {
return false;
}
// FIXASC end
/**
* Fixes the super types of anonymous inner classes These kinds of classes are always constructed so that they extend the super
* type, even if the super type is an interface. This is because during parse time we don't know if the super type is a class or
* interface, se we need to wait until after the resolve phase to fix this.
*/
public void fixAnonymousTypeBinding(GroovyCompilationUnitScope groovyCompilationUnitScope) {
if ((this.bits & ASTNode.IsAnonymousType) != 0) {
if (classNode.getInterfaces() != null && classNode.getInterfaces().length == 1
&& classNode.getSuperClass().getName().equals("java.lang.Object")) {
this.superInterfaces = new TypeReference[] { this.superclass };
this.binding.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) this.superclass.resolvedType };
this.superclass = null;
}
}
if (anonymousTypes != null) {
fixAnonymousTypeDeclarations(anonymousTypes, groovyCompilationUnitScope);
}
}
private void fixAnonymousTypeDeclarations(GroovyTypeDeclaration[] types, Scope parentScope) {
for (GroovyTypeDeclaration type : types) {
GroovyClassScope anonScope = new GroovyClassScope(parentScope, type);
type.scope = anonScope;
if (type.anonymousTypes != null) {
fixAnonymousTypeDeclarations(type.anonymousTypes, anonScope);
}
}
}
/**
* Anonymous types that are declared in this type's methods
*/
private GroovyTypeDeclaration[] anonymousTypes = null;
/**
* If this type is anonymous, points to the enclosing method
*/
public AbstractMethodDeclaration enclosingMethod;
public void addAnonymousType(GroovyTypeDeclaration anonymousType) {
if (anonymousTypes == null) {
anonymousTypes = new GroovyTypeDeclaration[] { anonymousType };
} else {
GroovyTypeDeclaration[] newTypes = new GroovyTypeDeclaration[anonymousTypes.length + 1];
System.arraycopy(anonymousTypes, 0, newTypes, 0, anonymousTypes.length);
newTypes[anonymousTypes.length] = anonymousType;
anonymousTypes = newTypes;
}
}
public GroovyTypeDeclaration[] getAnonymousTypes() {
return anonymousTypes;
}
}