/* * 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.utilities.dart.ParameterKind; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The abstract class {@code NormalFormalParameter} defines the behavior common to formal parameters * that are required (are not optional). * * <pre> * normalFormalParameter ::= * {@link FunctionTypedFormalParameter functionSignature} * | {@link FieldFormalParameter fieldFormalParameter} * | {@link SimpleFormalParameter simpleFormalParameter} * </pre> * * @coverage dart.engine.ast */ public abstract class NormalFormalParameter extends FormalParameter { /** * The documentation comment associated with this parameter, or {@code null} if this parameter * does not have a documentation comment associated with it. */ private Comment comment; /** * The annotations associated with this parameter. */ private NodeList<Annotation> metadata = new NodeList<Annotation>(this); /** * The name of the parameter being declared. */ private SimpleIdentifier identifier; /** * Initialize a newly created formal parameter. * * @param comment the documentation comment associated with this parameter * @param metadata the annotations associated with this parameter * @param identifier the name of the parameter being declared */ public NormalFormalParameter(Comment comment, List<Annotation> metadata, SimpleIdentifier identifier) { this.comment = becomeParentOf(comment); this.metadata.addAll(metadata); this.identifier = becomeParentOf(identifier); } /** * Return the documentation comment associated with this parameter, or {@code null} if this * parameter does not have a documentation comment associated with it. * * @return the documentation comment associated with this parameter */ public Comment getDocumentationComment() { return comment; } @Override public SimpleIdentifier getIdentifier() { return identifier; } @Override public ParameterKind getKind() { AstNode parent = getParent(); if (parent instanceof DefaultFormalParameter) { return ((DefaultFormalParameter) parent).getKind(); } return ParameterKind.REQUIRED; } /** * Return the annotations associated with this parameter. * * @return the annotations associated with this parameter */ public NodeList<Annotation> getMetadata() { return metadata; } /** * Set the documentation comment associated with this parameter to the given comment * * @param comment the documentation comment to be associated with this parameter */ public void setDocumentationComment(Comment comment) { this.comment = becomeParentOf(comment); } /** * Set the name of the parameter being declared to the given identifier. * * @param identifier the name of the parameter being declared */ public void setIdentifier(SimpleIdentifier identifier) { this.identifier = becomeParentOf(identifier); } /** * Set the metadata associated with this node to the given metadata. * * @param metadata the metadata to be associated with this node */ public void setMetadata(List<Annotation> metadata) { this.metadata.clear(); this.metadata.addAll(metadata); } @Override public void visitChildren(AstVisitor<?> visitor) { // // Note that subclasses are responsible for visiting the identifier because they often need to // visit other nodes before visiting the identifier. // if (commentIsBeforeAnnotations()) { safelyVisitChild(comment, visitor); metadata.accept(visitor); } else { for (AstNode child : getSortedCommentAndAnnotations()) { child.accept(visitor); } } } /** * Return {@code true} if the comment is lexically before any annotations. * * @return {@code true} if the comment is lexically before any annotations */ private boolean commentIsBeforeAnnotations() { if (comment == null || metadata.isEmpty()) { return true; } Annotation firstAnnotation = metadata.get(0); return comment.getOffset() < firstAnnotation.getOffset(); } /** * Return an array containing the comment and annotations associated with this parameter, sorted * in lexical order. * * @return the comment and annotations associated with this parameter in the order in which they * appeared in the original source */ private AstNode[] getSortedCommentAndAnnotations() { ArrayList<AstNode> childList = new ArrayList<AstNode>(); childList.add(comment); childList.addAll(metadata); AstNode[] children = childList.toArray(new AstNode[childList.size()]); Arrays.sort(children, AstNode.LEXICAL_ORDER); return children; } }