| /******************************************************************************* |
| * Copyright (c) 2002, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * xored software, Inc. - initial API and Implementation |
| * xored software, Inc. - Search All occurences bugfix, |
| * hilight only class name when class is in search results ( Alex Panchenko <alex@xored.com>) |
| *******************************************************************************/ |
| package org.eclipse.dltk.ast.declarations; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.dltk.ast.ASTListNode; |
| import org.eclipse.dltk.ast.ASTNode; |
| import org.eclipse.dltk.ast.ASTVisitor; |
| import org.eclipse.dltk.ast.DLTKToken; |
| import org.eclipse.dltk.ast.Modifiers; |
| import org.eclipse.dltk.ast.references.SimpleReference; |
| import org.eclipse.dltk.ast.statements.Block; |
| import org.eclipse.dltk.ast.utils.ASTUtil; |
| import org.eclipse.dltk.utils.CorePrinter; |
| |
| /** |
| * Used to represent types or classes. |
| */ |
| public class TypeDeclaration extends Declaration { |
| /** |
| * Body start position in associated file. |
| */ |
| protected int bodyEnd; |
| |
| /** |
| * Body end position in associated file. |
| */ |
| protected int bodyStart; |
| |
| /** |
| * Parent classes end position in associated file. |
| */ |
| protected int parentEnd; |
| |
| /** |
| * Parent classes start position in associated file. |
| */ |
| protected int parentStart; |
| |
| /** |
| * List of all super classes. Expression may be complex such as templates or |
| * other constructions. |
| */ |
| protected ASTListNode fSuperClasses; |
| |
| /** |
| * List of body statements. |
| */ |
| protected Block fBody; |
| |
| protected List fMethods; |
| |
| protected List fTypes; |
| |
| protected List fVariables; |
| |
| protected String enclosingTypeName; |
| |
| public TypeDeclaration(DLTKToken name, int start, int end) { |
| |
| super(name, start, end); |
| } |
| |
| /** |
| * Creates new type declaration from type name ANTLR token, start and end |
| * position. |
| * |
| * @param name |
| * type name. |
| * @param start |
| * type start position in associated file. |
| * @param end |
| * type end position in associated file. |
| */ |
| public TypeDeclaration(String name, int nameStart, int nameEnd, int start, |
| int end) { |
| |
| super(start, end); |
| setName(name); |
| setNameStart(nameStart); |
| setNameEnd(nameEnd); |
| this.enclosingTypeName = ""; //$NON-NLS-1$ |
| } |
| |
| public List getMethodList() { |
| if (this.fMethods == null) { |
| initInners(); |
| } |
| return this.fMethods; |
| } |
| |
| public List getFieldList() { |
| if (this.fVariables == null) { |
| initInners(); |
| } |
| return this.fVariables; |
| } |
| |
| public List getTypeList() { |
| if (this.fTypes == null) { |
| initInners(); |
| } |
| return this.fTypes; |
| } |
| |
| public void setEnclosingTypeName(String name) { |
| if (name.startsWith("$")) { //$NON-NLS-1$ |
| name = name.substring(1); |
| } |
| if (name != null && name.length() > 0) { |
| this.enclosingTypeName = name; |
| } |
| } |
| |
| public String getEnclosingTypeName() { |
| return this.enclosingTypeName; |
| } |
| |
| /** |
| * Creates type declaration from name token. |
| * |
| * @param name |
| * name ANTRL token. |
| */ |
| public TypeDeclaration(DLTKToken name) { |
| |
| super(); |
| this.setName(name.getText()); |
| } |
| |
| /** |
| * Used to walk on tree. traverse order: superclasses, body. |
| */ |
| @Override |
| public void traverse(ASTVisitor visitor) throws Exception { |
| |
| if (visitor.visit(this)) { |
| if (this.getSuperClasses() != null) { |
| this.getSuperClasses().traverse(visitor); |
| } |
| if (this.fBody != null) { |
| fBody.traverse(visitor); |
| } |
| visitor.endvisit(this); |
| } |
| } |
| |
| /** |
| * Return list of superclass declaration expressions. |
| * |
| * @return |
| */ |
| public ASTListNode getSuperClasses() { |
| |
| return this.fSuperClasses; |
| } |
| |
| /** |
| * Set superclases expression list. |
| * |
| * @param exprList |
| */ |
| public void setSuperClasses(ASTListNode exprList) { |
| |
| this.fSuperClasses = exprList; |
| } |
| |
| /** |
| * Add superclass expression to list of superclasses. List would be created |
| * if not yet. |
| * |
| * @param expression |
| */ |
| public void addSuperClass(ASTNode expression) { |
| |
| if (this.fSuperClasses == null) { |
| this.fSuperClasses = new ASTListNode(); |
| } |
| |
| this.fSuperClasses.addNode(expression); |
| |
| } |
| |
| /** |
| * Return TypeDeclaration kind. |
| */ |
| @Override |
| public int getKind() { |
| |
| return D_CLASS; |
| } |
| |
| /** |
| * Return body end position in associated file. |
| * |
| * @return |
| */ |
| public int getBodyEnd() { |
| if (getBody() != null) { |
| return getBody().sourceEnd(); |
| } |
| return bodyEnd; |
| } |
| |
| /** |
| * Sets body end position in associated file. |
| * |
| * @param bodyEnd |
| */ |
| protected void setBodyEnd(int bodyEnd) { |
| |
| this.bodyEnd = bodyEnd; |
| } |
| |
| /** |
| * Return body start position in associated file. |
| * |
| * @return |
| */ |
| public int getBodyStart() { |
| if (getBody() != null) { |
| return getBody().sourceStart(); |
| } |
| return bodyStart; |
| } |
| |
| /** |
| * Set body start position in associated file. |
| */ |
| protected void setBodyStart(int bodyStart) { |
| |
| this.bodyStart = bodyStart; |
| } |
| |
| /** |
| * Use sourceEnd() instead. |
| * |
| * @return |
| * @deprecated |
| */ |
| |
| @Deprecated |
| public int getDeclarationSourceEnd() { |
| |
| return this.sourceEnd(); |
| } |
| |
| /** |
| * Use setEnd instead |
| * |
| * @param declarationSourceEnd |
| * @deprecated |
| */ |
| |
| @Deprecated |
| protected void setDeclarationSourceEnd(int declarationSourceEnd) { |
| this.setEnd(declarationSourceEnd); |
| } |
| |
| /** |
| * Use sourceStart instead. |
| * |
| * @return |
| * @deprecated |
| */ |
| |
| @Deprecated |
| public int getDeclarationSourceStart() { |
| |
| return this.sourceStart(); |
| } |
| |
| /** |
| * Used setStart instead |
| * |
| * @param declarationSourceStart |
| * @deprecated |
| */ |
| |
| @Deprecated |
| protected void setDeclarationSourceStart(int declarationSourceStart) { |
| |
| this.setStart(declarationSourceStart); |
| } |
| |
| /** |
| * Return parents end position in associated file. |
| * |
| * @return |
| */ |
| public int getParentEnd() { |
| |
| return parentEnd; |
| } |
| |
| /** |
| * Sets parents end position in associated file. |
| * |
| * @param parentEnd |
| */ |
| protected void setParentEnd(int parentEnd) { |
| |
| this.parentEnd = parentEnd; |
| } |
| |
| /** |
| * Return parents start position in associated file. |
| * |
| * @return |
| */ |
| public int getParentStart() { |
| |
| return parentStart; |
| } |
| |
| /** |
| * Sets parents start position in associated file. |
| * |
| * @param parentStart |
| */ |
| protected void setParentStart(int parentStart) { |
| |
| this.parentStart = parentStart; |
| } |
| |
| /** |
| * Set inner statements. |
| * |
| * @param body |
| */ |
| public void setBody(Block body) { |
| |
| this.fBody = body; |
| if (body != null) { |
| this.bodyStart = body.sourceStart(); |
| this.bodyEnd = body.sourceEnd(); |
| // this.setEnd(body.sourceEnd()); //XXX: why? |
| } |
| } |
| |
| public Block getBody() { |
| return this.fBody; |
| } |
| |
| /** |
| * Set inner statements with start and end position in associated file. |
| * |
| * @param startBody |
| * start position. |
| * @param body |
| * inner statements. |
| * @param endBody |
| * end position. |
| */ |
| public void setBody(int startBody, Block body, int endBody) { |
| |
| this.setBody(body); |
| this.setBodyStart(startBody); |
| this.setBodyEnd(endBody); |
| } |
| |
| /** |
| * Return super class names. |
| * |
| * @return |
| */ |
| public List<String> getSuperClassNames() { |
| if (this.fSuperClasses != null) { |
| final List<ASTNode> superClasses = this.fSuperClasses.getChilds(); |
| final List<String> names = new ArrayList<>( |
| superClasses.size()); |
| for (Iterator<ASTNode> i = superClasses.iterator(); i.hasNext();) { |
| final ASTNode expr = i.next(); |
| final String name = resolveSuperClassReference(expr); |
| if (name != null) { |
| names.add(name); |
| } |
| } |
| return names; |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| |
| public String resolveSuperClassReference(ASTNode node) { |
| if (node instanceof SimpleReference) { |
| return ((SimpleReference) node).getName(); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Testing purpose only. Prints type and all inner statements to printer. |
| */ |
| @Override |
| public void printNode(CorePrinter output) { |
| |
| output.formatPrintLn("Type" + this.getSourceRange().toString() //$NON-NLS-1$ |
| + this.getNameSourceRange().toString() + ":"); //$NON-NLS-1$ |
| String name = this.getName(); |
| if (name != null) { |
| output.formatPrintLn(name); |
| } |
| if (this.fSuperClasses != null) { |
| output.formatPrintLn("("); //$NON-NLS-1$ |
| this.fSuperClasses.printNode(output); |
| output.formatPrintLn(")"); //$NON-NLS-1$ |
| } |
| if (this.fBody != null) { |
| this.fBody.printNode(output); |
| } |
| } |
| |
| public MethodDeclaration[] getMethods() { |
| if (this.fMethods == null) { |
| initInners(); |
| } |
| return ASTUtil.getMethods(this.getStatements(), this.fMethods); |
| } |
| |
| public TypeDeclaration[] getTypes() { |
| if (this.fTypes == null) { |
| initInners(); |
| } |
| return ASTUtil.getTypes(this.getStatements(), this.fTypes); |
| } |
| |
| private void initInners() { |
| this.fMethods = new ArrayList(); |
| this.fTypes = new ArrayList(); |
| this.fVariables = new ArrayList(); |
| } |
| |
| public List getStatements() { |
| if (this.fBody == null) { |
| this.fBody = new Block(this.sourceStart(), this.sourceEnd(), null); |
| } |
| return this.fBody.getStatements(); |
| } |
| |
| public ASTNode[] getNonTypeOrMethodNode() { |
| List statements = getStatements(); |
| if (statements != null) { |
| Iterator i = statements.iterator(); |
| List results = new ArrayList(); |
| while (i.hasNext()) { |
| ASTNode node = (ASTNode) i.next(); |
| if (!(node instanceof TypeDeclaration) |
| && !(node instanceof MethodDeclaration)) { |
| results.add(node); |
| } |
| } |
| return (ASTNode[]) results.toArray(new ASTNode[results.size()]); |
| } |
| return null; |
| } |
| |
| public FieldDeclaration[] getVariables() { |
| if (this.fVariables == null) { |
| initInners(); |
| } |
| return ASTUtil.getVariables(this.getStatements(), this.fVariables); |
| } |
| |
| @Override |
| public String debugString() { |
| String prev = super.debugString(); |
| if ((this.getModifiers() & Modifiers.AccModule) != 0) |
| prev += "(module)"; //$NON-NLS-1$ |
| return prev; |
| } |
| |
| @Override |
| public int matchStart() { |
| return getNameStart(); |
| } |
| |
| @Override |
| public int matchLength() { |
| return getNameEnd() - getNameStart(); |
| } |
| |
| } |