/*
* Copyright 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
*
* 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 com.google.dart.engine.ast;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.scanner.Token;
import java.util.List;
/**
* Instances of the class {@code ClassDeclaration} represent the declaration of a class.
*
* <pre>
* classDeclaration ::=
* 'abstract'? 'class' {@link SimpleIdentifier name} {@link TypeParameterList typeParameterList}?
* ({@link ExtendsClause extendsClause} {@link WithClause withClause}?)?
* {@link ImplementsClause implementsClause}?
* '{' {@link ClassMember classMember}* '}'
* </pre>
*
* @coverage dart.engine.ast
*/
public class ClassDeclaration extends CompilationUnitMember {
/**
* The 'abstract' keyword, or {@code null} if the keyword was absent.
*/
private Token abstractKeyword;
/**
* The token representing the 'class' keyword.
*/
private Token classKeyword;
/**
* The name of the class being declared.
*/
private SimpleIdentifier name;
/**
* The type parameters for the class, or {@code null} if the class does not have any type
* parameters.
*/
private TypeParameterList typeParameters;
/**
* The extends clause for the class, or {@code null} if the class does not extend any other class.
*/
private ExtendsClause extendsClause;
/**
* The with clause for the class, or {@code null} if the class does not have a with clause.
*/
private WithClause withClause;
/**
* The implements clause for the class, or {@code null} if the class does not implement any
* interfaces.
*/
private ImplementsClause implementsClause;
/**
* The native clause for the class, or {@code null} if the class does not have a native clause.
*/
private NativeClause nativeClause;
/**
* The left curly bracket.
*/
private Token leftBracket;
/**
* The members defined by the class.
*/
private NodeList<ClassMember> members = new NodeList<ClassMember>(this);
/**
* The right curly bracket.
*/
private Token rightBracket;
/**
* Initialize a newly created class declaration.
*
* @param comment the documentation comment associated with this class
* @param metadata the annotations associated with this class
* @param abstractKeyword the 'abstract' keyword, or {@code null} if the keyword was absent
* @param classKeyword the token representing the 'class' keyword
* @param name the name of the class being declared
* @param typeParameters the type parameters for the class
* @param extendsClause the extends clause for the class
* @param withClause the with clause for the class
* @param implementsClause the implements clause for the class
* @param leftBracket the left curly bracket
* @param members the members defined by the class
* @param rightBracket the right curly bracket
*/
public ClassDeclaration(Comment comment, List<Annotation> metadata, Token abstractKeyword,
Token classKeyword, SimpleIdentifier name, TypeParameterList typeParameters,
ExtendsClause extendsClause, WithClause withClause, ImplementsClause implementsClause,
Token leftBracket, List<ClassMember> members, Token rightBracket) {
super(comment, metadata);
this.abstractKeyword = abstractKeyword;
this.classKeyword = classKeyword;
this.name = becomeParentOf(name);
this.typeParameters = becomeParentOf(typeParameters);
this.extendsClause = becomeParentOf(extendsClause);
this.withClause = becomeParentOf(withClause);
this.implementsClause = becomeParentOf(implementsClause);
this.leftBracket = leftBracket;
this.members.addAll(members);
this.rightBracket = rightBracket;
}
@Override
public <R> R accept(AstVisitor<R> visitor) {
return visitor.visitClassDeclaration(this);
}
/**
* Return the 'abstract' keyword, or {@code null} if the keyword was absent.
*
* @return the 'abstract' keyword
*/
public Token getAbstractKeyword() {
return abstractKeyword;
}
/**
* Return the token representing the 'class' keyword.
*
* @return the token representing the 'class' keyword
*/
public Token getClassKeyword() {
return classKeyword;
}
/**
* Return the constructor declared in the class with the given name.
*
* @param name the name of the constructor to find, {@code null} for default
* @return the found constructor or {@code null} if not found
*/
public ConstructorDeclaration getConstructor(String name) {
for (ClassMember classMember : members) {
if (classMember instanceof ConstructorDeclaration) {
ConstructorDeclaration constructor = (ConstructorDeclaration) classMember;
SimpleIdentifier constructorName = constructor.getName();
if (name == null && constructorName == null) {
return constructor;
}
if (constructorName != null && constructorName.getName().equals(name)) {
return constructor;
}
}
}
return null;
}
@Override
public ClassElement getElement() {
return name != null ? (ClassElement) name.getStaticElement() : null;
}
@Override
public Token getEndToken() {
return rightBracket;
}
/**
* Return the extends clause for this class, or {@code null} if the class does not extend any
* other class.
*
* @return the extends clause for this class
*/
public ExtendsClause getExtendsClause() {
return extendsClause;
}
/**
* Return the field declared in the class with the given name.
*
* @param name the name of the field to find
* @return the found field or {@code null} if not found
*/
public VariableDeclaration getField(String name) {
for (ClassMember classMember : members) {
if (classMember instanceof FieldDeclaration) {
FieldDeclaration fieldDeclaration = (FieldDeclaration) classMember;
NodeList<VariableDeclaration> fields = fieldDeclaration.getFields().getVariables();
for (VariableDeclaration field : fields) {
SimpleIdentifier fieldName = field.getName();
if (fieldName != null && name.equals(fieldName.getName())) {
return field;
}
}
}
}
return null;
}
/**
* Return the implements clause for the class, or {@code null} if the class does not implement any
* interfaces.
*
* @return the implements clause for the class
*/
public ImplementsClause getImplementsClause() {
return implementsClause;
}
/**
* Return the left curly bracket.
*
* @return the left curly bracket
*/
public Token getLeftBracket() {
return leftBracket;
}
/**
* Return the members defined by the class.
*
* @return the members defined by the class
*/
public NodeList<ClassMember> getMembers() {
return members;
}
/**
* Return the method declared in the class with the given name.
*
* @param name the name of the method to find
* @return the found method or {@code null} if not found
*/
public MethodDeclaration getMethod(String name) {
for (ClassMember classMember : members) {
if (classMember instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) classMember;
SimpleIdentifier methodName = method.getName();
if (methodName != null && name.equals(methodName.getName())) {
return method;
}
}
}
return null;
}
/**
* Return the name of the class being declared.
*
* @return the name of the class being declared
*/
public SimpleIdentifier getName() {
return name;
}
/**
* Return the native clause for this class, or {@code null} if the class does not have a native
* cluse.
*
* @return the native clause for this class
*/
public NativeClause getNativeClause() {
return nativeClause;
}
/**
* Return the right curly bracket.
*
* @return the right curly bracket
*/
public Token getRightBracket() {
return rightBracket;
}
/**
* Return the type parameters for the class, or {@code null} if the class does not have any type
* parameters.
*
* @return the type parameters for the class
*/
public TypeParameterList getTypeParameters() {
return typeParameters;
}
/**
* Return the with clause for the class, or {@code null} if the class does not have a with clause.
*
* @return the with clause for the class
*/
public WithClause getWithClause() {
return withClause;
}
/**
* Return {@code true} if this class is declared to be an abstract class.
*
* @return {@code true} if this class is declared to be an abstract class
*/
public boolean isAbstract() {
return abstractKeyword != null;
}
/**
* Set the 'abstract' keyword to the given keyword.
*
* @param abstractKeyword the 'abstract' keyword
*/
public void setAbstractKeyword(Token abstractKeyword) {
this.abstractKeyword = abstractKeyword;
}
/**
* Set the token representing the 'class' keyword to the given token.
*
* @param classKeyword the token representing the 'class' keyword
*/
public void setClassKeyword(Token classKeyword) {
this.classKeyword = classKeyword;
}
/**
* Set the extends clause for this class to the given clause.
*
* @param extendsClause the extends clause for this class
*/
public void setExtendsClause(ExtendsClause extendsClause) {
this.extendsClause = becomeParentOf(extendsClause);
}
/**
* Set the implements clause for the class to the given clause.
*
* @param implementsClause the implements clause for the class
*/
public void setImplementsClause(ImplementsClause implementsClause) {
this.implementsClause = becomeParentOf(implementsClause);
}
/**
* Set the left curly bracket to the given token.
*
* @param leftBracket the left curly bracket
*/
public void setLeftBracket(Token leftBracket) {
this.leftBracket = leftBracket;
}
/**
* Set the name of the class being declared to the given identifier.
*
* @param identifier the name of the class being declared
*/
public void setName(SimpleIdentifier identifier) {
name = becomeParentOf(identifier);
}
/**
* Set the native clause for this class to the given clause.
*
* @param nativeClause the native clause for this class
*/
public void setNativeClause(NativeClause nativeClause) {
this.nativeClause = becomeParentOf(nativeClause);
}
/**
* Set the right curly bracket to the given token.
*
* @param rightBracket the right curly bracket
*/
public void setRightBracket(Token rightBracket) {
this.rightBracket = rightBracket;
}
/**
* Set the type parameters for the class to the given list of type parameters.
*
* @param typeParameters the type parameters for the class
*/
public void setTypeParameters(TypeParameterList typeParameters) {
this.typeParameters = becomeParentOf(typeParameters);
}
/**
* Set the with clause for the class to the given clause.
*
* @param withClause the with clause for the class
*/
public void setWithClause(WithClause withClause) {
this.withClause = becomeParentOf(withClause);
}
@Override
public void visitChildren(AstVisitor<?> visitor) {
super.visitChildren(visitor);
safelyVisitChild(name, visitor);
safelyVisitChild(typeParameters, visitor);
safelyVisitChild(extendsClause, visitor);
safelyVisitChild(withClause, visitor);
safelyVisitChild(implementsClause, visitor);
safelyVisitChild(nativeClause, visitor);
getMembers().accept(visitor);
}
@Override
protected Token getFirstTokenAfterCommentAndMetadata() {
if (abstractKeyword != null) {
return abstractKeyword;
}
return classKeyword;
}
}