blob: 9a470a049f8b96056c56c2ec707baf3c169ebfb8 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}