| /******************************************************************************* |
| * Copyright (c) 2012 NumberFour AG |
| * |
| * 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: |
| * NumberFour AG - initial API and Implementation (Alex Panchenko) |
| *******************************************************************************/ |
| package org.eclipse.dltk.javascript.structure; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| import org.eclipse.dltk.javascript.ast.Identifier; |
| |
| public abstract class ParentNode extends StructureNode implements IParentNode { |
| |
| public ParentNode(IParentNode parent) { |
| super(parent); |
| } |
| |
| static abstract class NodeReference implements IStructureNode { |
| |
| final Identifier identifier; |
| |
| public NodeReference(Identifier identifier) { |
| this.identifier = identifier; |
| } |
| |
| public int start() { |
| return identifier.start(); |
| } |
| |
| public boolean isManyChildren() { |
| return false; |
| } |
| |
| public List<? extends IStructureNode> getChildren() { |
| return Collections.emptyList(); |
| } |
| |
| public IParentNode getParent() { |
| return null; |
| } |
| |
| public IScope getScope() { |
| return null; |
| } |
| |
| @Override |
| public String toString() { |
| return getClass().getSimpleName() + "(" + identifier.getName() |
| + ")"; |
| } |
| |
| } |
| |
| static class LocalReference extends NodeReference { |
| |
| final IDeclaration declaration; |
| |
| public LocalReference(Identifier identifier, IDeclaration declaration) { |
| super(identifier); |
| this.declaration = declaration; |
| } |
| |
| public void reportStructure(IStructureRequestor requestor, |
| IStructureContext context) { |
| requestor.acceptLocalReference(identifier, declaration); |
| } |
| } |
| |
| static class FieldReference extends NodeReference { |
| |
| public FieldReference(Identifier identifier) { |
| super(identifier); |
| } |
| |
| public void reportStructure(IStructureRequestor requestor, |
| IStructureContext context) { |
| requestor.acceptFieldReference(identifier); |
| } |
| } |
| |
| static class MethodRefence extends NodeReference { |
| |
| final int argCount; |
| |
| public MethodRefence(Identifier identifier, int argCount) { |
| super(identifier); |
| this.argCount = argCount; |
| } |
| |
| public void reportStructure(IStructureRequestor requestor, |
| IStructureContext context) { |
| requestor.acceptMethodReference(identifier, argCount); |
| } |
| } |
| |
| private List<NodeReference> references; |
| |
| private void addReference(NodeReference reference) { |
| if (references == null) { |
| references = new ArrayList<NodeReference>(); |
| } |
| references.add(reference); |
| } |
| |
| public void addLocalReference(Identifier node, IDeclaration resolved) { |
| addReference(new LocalReference(node, resolved)); |
| } |
| |
| public void addMethodReference(Identifier identifier, int argCount) { |
| addReference(new MethodRefence(identifier, argCount)); |
| } |
| |
| public void addFieldReference(Identifier identifier) { |
| addReference(new FieldReference(identifier)); |
| } |
| |
| protected boolean isStructureKnown() { |
| return true; |
| } |
| |
| public void addToScope(IStructureNode child) { |
| if (!isStructureKnown()) { |
| getScope().addChild(child); |
| } |
| } |
| |
| @Override |
| protected void reportChildrenStructure(IStructureRequestor requestor, |
| IStructureContext context) { |
| if (references != null) { |
| final List<? extends IStructureNode> children = getChildren(); |
| final List<IStructureNode> nodes = new ArrayList<IStructureNode>( |
| children.size() + references.size()); |
| nodes.addAll(children); |
| nodes.addAll(references); |
| Collections.sort(nodes, new Comparator<IStructureNode>() { |
| public int compare(IStructureNode o1, IStructureNode o2) { |
| return o1.start() - o2.start(); |
| } |
| }); |
| for (IStructureNode node : nodes) { |
| node.reportStructure(requestor, context); |
| } |
| } else { |
| super.reportChildrenStructure(requestor, context); |
| } |
| } |
| |
| } |