| /******************************************************************************* |
| * 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 static java.lang.Math.min; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.dltk.compiler.IElementRequestor.MethodInfo; |
| import org.eclipse.dltk.core.ISourceNode; |
| import org.eclipse.dltk.internal.javascript.parser.JSModifiers; |
| import org.eclipse.dltk.javascript.ast.Argument; |
| import org.eclipse.dltk.javascript.ast.Expression; |
| import org.eclipse.dltk.javascript.ast.FunctionStatement; |
| import org.eclipse.dltk.javascript.typeinference.ReferenceLocation; |
| import org.eclipse.dltk.javascript.typeinfo.IModelBuilder.IMethod; |
| import org.eclipse.dltk.javascript.typeinfo.IModelBuilder.IParameter; |
| import org.eclipse.dltk.javascript.typeinfo.model.JSType; |
| |
| public abstract class FunctionNode extends Scope { |
| |
| final FunctionStatement function; |
| final IMethod method; |
| private String returnType; |
| |
| public FunctionNode(IParentNode parent, FunctionStatement function, |
| IMethod method) { |
| super(parent); |
| this.function = function; |
| this.method = method; |
| } |
| |
| public void buildArgumentNodes() { |
| for (Argument argument : function.getArguments()) { |
| final String name = argument.getArgumentName(); |
| final IParameter parameter = method.getParameter(name); |
| addChild(new ArgumentNode(this, name, |
| parameter != null ? parameter.getType() : null, |
| ReferenceLocation.create(method.getLocation().getSource(), |
| argument.start(), argument.end()))); |
| } |
| } |
| |
| public JSType getType() { |
| return method.getType(); |
| } |
| |
| public void setReturnType(String returnType) { |
| this.returnType = returnType; |
| } |
| |
| public int start() { |
| return getNameNode().start(); |
| } |
| |
| protected String argumentsToString() { |
| final StringBuilder sb = new StringBuilder(); |
| for (ArgumentNode argument : getArguments()) { |
| if (sb.length() != 0) { |
| sb.append(','); |
| } |
| sb.append(argument.getName()); |
| if (argument.getType() != null) { |
| sb.append(':'); |
| sb.append(argument.getType().getName()); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| protected List<ArgumentNode> getArguments() { |
| List<ArgumentNode> result = null; |
| for (IStructureNode node : getChildren()) { |
| if (node instanceof ArgumentNode) { |
| if (result == null) { |
| result = new ArrayList<ArgumentNode>(function |
| .getArguments().size()); |
| } |
| result.add((ArgumentNode) node); |
| } |
| } |
| return result != null ? result : Collections.<ArgumentNode> emptyList(); |
| } |
| |
| @Override |
| public void reportStructure(IStructureRequestor requestor, |
| IStructureContext context) { |
| final boolean allowed = context.allow(IStructureContext.METHOD); |
| if (allowed) { |
| final MethodInfo info = new MethodInfo(); |
| final ISourceNode nameNode = getNameNode(); |
| info.declarationStart = min(nameNode.start(), function.start()); |
| info.name = getName(); |
| if (method.getVisibility() != null) { |
| info.modifiers |= method.getVisibility().getFlags(); |
| } |
| if (method.isDeprecated()) { |
| info.modifiers |= JSModifiers.DEPRECATED; |
| } |
| info.nameSourceStart = nameNode.start(); |
| info.nameSourceEnd = nameNode.end() - 1; |
| final List<ArgumentNode> arguments = getArguments(); |
| if (!arguments.isEmpty()) { |
| final int argumentCount = arguments.size(); |
| info.parameterNames = new String[argumentCount]; |
| info.parameterTypes = new String[argumentCount]; |
| for (int i = 0; i < argumentCount; ++i) { |
| final ArgumentNode argument = arguments.get(i); |
| info.parameterNames[i] = argument.getName(); |
| info.parameterTypes[i] = typeToModel(argument.getType()); |
| } |
| } |
| info.returnType = typeToModel(getType()); |
| if (info.returnType == null) |
| info.returnType = returnType; |
| info.isConstructor = method.isConstructor(); |
| requestor.enterMethod(info, getStructureNameNode(), function, |
| method); |
| } |
| context.pushMask(IStructureContext.FIELD); |
| super.reportStructure(requestor, context); |
| context.popMask(); |
| if (allowed) { |
| requestor.exitMethod(function.end() - 1); |
| } |
| } |
| |
| protected Expression getStructureNameNode() { |
| return function.getName(); |
| } |
| |
| protected abstract String getName(); |
| |
| public abstract ISourceNode getNameNode(); |
| |
| } |