/* * (non-Javadoc) * @see com.aptana.editor.js.parsing.ast.JSTreeWalker#visit(com.aptana.editor.js.parsing.ast.JSFunctionNode) */ @Override public void visit(JSFunctionNode node) { List<String> types = new ArrayList<String>(); JSScope scope = this.getActiveScope(node.getBody().getStartingOffset()); boolean foundReturnExpression = false; // infer return types for (JSReturnNode returnValue : node.getReturnNodes()) { IParseNode expression = returnValue.getExpression(); if (!expression.isEmpty()) { foundReturnExpression = true; types.addAll(this.getTypes(expression, scope)); } } // If we couldn't infer a return type and we had a return // expression, then have it return Object if (foundReturnExpression && types.isEmpty()) { types.add(JSTypeConstants.OBJECT_TYPE); } // build function type, including return values String type = JSTypeUtil.toFunctionType(types); this.addType(type); }
/* * (non-Javadoc) * @see * com.aptana.editor.js.parsing.ast.JSTreeWalker#visit(com.aptana.editor.js.parsing.ast.JSArithmeticOperatorNode) */ @Override public void visit(JSBinaryArithmeticOperatorNode node) { String type = JSTypeConstants.NUMBER_TYPE; if (node.getNodeType() == IJSNodeTypes.ADD) { IParseNode lhs = node.getLeftHandSide(); IParseNode rhs = node.getRightHandSide(); // NOTE: Iterate down the tree until we find the first non-addition node or the first string while (lhs.getNodeType() == IJSNodeTypes.ADD) { rhs = lhs.getLastChild(); lhs = lhs.getFirstChild(); if (rhs instanceof JSStringNode) { break; } } if (lhs instanceof JSStringNode || rhs instanceof JSStringNode) { type = JSTypeConstants.STRING_TYPE; } else { List<String> lhsTypes = this.getTypes(lhs); List<String> rhsTypes = this.getTypes(rhs); if (lhsTypes.contains(JSTypeConstants.STRING_TYPE) || rhsTypes.contains(JSTypeConstants.STRING_TYPE)) { type = JSTypeConstants.STRING_TYPE; } } } this.addType(type); }
@Override public Object getParent(Object element) { if (element instanceof CommonOutlineItem) { IParseNode node = ((CommonOutlineItem) element).getReferenceNode(); IParseNode parent = node.getParent(); if (parent instanceof ParseRootNode) { // we're at the root of the nested language, which is not displayed; go one level up parent = parent.getParent(); } return getOutlineItem(parent); } return super.getParent(element); }
/** * @param document * @param hasBlockedChild * @param node */ public FormatterJSIfNode( IFormatterDocument document, boolean hasBlockedChild, IParseNode node, boolean hasCommentBefore) { super(document, hasBlockedChild, node, hasCommentBefore); // Check if this node is located in the 'false' block of a parent 'if'. In that case, we can say // for sure that // this 'if' arrives right after an 'else'. if (node.getParent().getNodeType() == JSNodeTypes.IF) { JSIfNode parentIfNode = (JSIfNode) node.getParent(); inElseIf = parentIfNode.getFalseBlock() == node; } }
private void processPHPBlock(IParseNode root, int sourceLength) throws IOException, Exception // $codepro.audit.disable { Symbol startTag = getCurrentSymbol(); advance(); // finds the entire php block int start = getCurrentSymbol().getStart(); int end = start; short id = getCurrentSymbol().getId(); while (id != PHTMLTokens.PHP_END && id != PHTMLTokens.EOF) { end = getCurrentSymbol().getEnd(); advance(); id = getCurrentSymbol().getId(); } IParseNode result = getParseResult(IPHPConstants.CONTENT_TYPE_PHP, start, end); if (result != null) { Symbol endTag = getCurrentSymbol(); ParseNode phpNode = new ParseNode(IPHPConstants.CONTENT_TYPE_PHP); int endOffset; if ("?>".equals(endTag.value)) // $NON-NLS-1$ { endOffset = endTag.getEnd() + 1; } else { endOffset = endTag.getEnd(); } phpNode.setLocation(startTag.getStart(), Math.min(endOffset, sourceLength - 1)); root.addChild(phpNode); } }
@Override public CommonOutlineItem getOutlineItem(IParseNode node) { if (node instanceof HTMLNode) { return new HTMLOutlineItem(node.getNameNode().getNameRange(), node); } return super.getOutlineItem(node); }
/* * (non-Javadoc) * @see com.aptana.editor.js.parsing.ast.JSTreeWalker#visit(com.aptana.editor.js.parsing.ast.JSIdentifierNode) */ @Override public void visit(JSIdentifierNode node) { String name = node.getText(); Collection<PropertyElement> properties = null; if (this._scope != null && this._scope.hasSymbol(name)) { IParseNode parent = node.getParent(); if (parent != null && parent.getNodeType() == IJSNodeTypes.PARAMETERS) { // special handling of parameters to potentially get the type // from documentation and to prevent an infinite loop since // parameters point to themselves in the symbol table this.addParameterTypes(node); } else { // Check the local scope for type first JSSymbolTypeInferrer symbolInferrer = new JSSymbolTypeInferrer(this._scope, this._index, this._location); PropertyElement property = symbolInferrer.getSymbolPropertyElement(name); if (property != null) { // We found a match in the local scope properties = CollectionsUtil.newList(property); } else { // No match in the local scope, query the globals in index properties = this._queryHelper.getGlobals(this._index, getProject(), getFileName(), name); } } } else { // Scope says it doesn't has a symbol with that name, so query the globals in index properties = this._queryHelper.getGlobals(this._index, getProject(), getFileName(), name); } // Hopefully we found at least one match... if (properties != null) { for (PropertyElement property : properties) { if (property instanceof FunctionElement) { FunctionElement function = (FunctionElement) property; for (String type : function.getSignatureTypes()) { this.addType(type); } } else { for (String type : property.getTypeNames()) { this.addType(type); } } } } }
private void filterRecursively(IParseNode[] nodes, List<CommonOutlineItem> list) { IPHPParseNode element; for (IParseNode node : nodes) { if (node instanceof IPHPParseNode) { element = (IPHPParseNode) node; // filters out any item that should not be in the outline if (!element.isFilteredFromOutline()) { list.add(getOutlineItem(element)); } else { // the node may have children that we don't want to filter (like a function within an 'if' // statement). filterRecursively(node.getChildren(), list); } } else if (!(node instanceof HTMLTextNode)) { list.add(getOutlineItem(node)); } } }
/* (non-Javadoc) * @see com.aptana.editor.json.parsing.ast.JSONTreeWalker#visit(com.aptana.editor.json.parsing.ast.JSONEntryNode) */ @Override public void visit(JSONEntryNode node) { JSONEntryFormatNode entry = new JSONEntryFormatNode(_document); IParseNode name = node.getFirstChild(); Symbol colon = node.getColon(); IParseNode value = node.getLastChild(); IFormatterTextNode nameText = createTextNode(_document, name.getStartingOffset(), name.getEndingOffset() + 1); IFormatterTextNode colonText = createTextNode(_document, colon.getStart(), colon.getEnd() + 1); // add children entry.addChild(nameText); entry.addChild(colonText); // push node, visit children, then remove from stack push(entry); this.visit(value); checkedPop(entry, node.getEndingOffset() + 1); }
@Override public CommonOutlineItem getOutlineItem(IParseNode node) { if (node == null) { return null; } if (node instanceof IPHPParseNode) { return new PHPOutlineItem(node.getNameNode().getNameRange(), node); } else { return super.getOutlineItem(node); } }
/* * (non-Javadoc) * @see com.aptana.editor.js.parsing.ast.JSTreeWalker#visit(com.aptana.editor.js.parsing.ast.JSGetPropertyNode) */ @Override public void visit(JSGetPropertyNode node) { IParseNode lhs = node.getLeftHandSide(); if (lhs instanceof JSNode) { IParseNode rhs = node.getRightHandSide(); String memberName = rhs.getText(); for (String typeName : this.getTypes(lhs)) { // Fix up type names as might be necessary typeName = JSTypeMapper.getInstance().getMappedType(typeName); // TODO Combine with similar code from ParseUtil.getParentObjectTypes if (JSTypeConstants.FUNCTION_JQUERY.equals(typeName) && lhs instanceof JSIdentifierNode && (JSTypeConstants.DOLLAR.equals(lhs.getText()) || JSTypeConstants.JQUERY.equals(lhs.getText()))) { typeName = JSTypeConstants.CLASS_JQUERY; } // lookup up rhs name in type and add that value's type here Collection<PropertyElement> properties = this._queryHelper.getTypeMembers(this._index, typeName, memberName); if (properties != null) { for (PropertyElement property : properties) { if (property instanceof FunctionElement) { FunctionElement function = (FunctionElement) property; for (String type : function.getSignatureTypes()) { this.addType(type); } } else { for (String type : property.getTypeNames()) { this.addType(type); } } } } } } }
/** * A private helper function for {@link #toTreeString(IParseNode)} * * @param buffer * @param node */ private static void toTreeString(List<String> buffer, IParseNode node) { // TODO: Move to an iterative (non-recursive) implementation if this gets used outside of unit // testing buffer.add("("); // $NON-NLS-1$ buffer.add(node.getElementName()); if (node.hasChildren()) { IParseNode lastChild = node.getLastChild(); buffer.add(" "); // $NON-NLS-1$ for (IParseNode child : node) { toTreeString(buffer, child); if (child != lastChild) { buffer.add(" "); // $NON-NLS-1$ } } } buffer.add(")"); // $NON-NLS-1$ }
/** * addParameterTypes * * @param identifierNode */ private void addParameterTypes(JSIdentifierNode identifierNode) { IParseNode parent = identifierNode.getParent(); IParseNode grandparent = (parent != null) ? parent.getParent() : null; boolean foundType = false; if (grandparent != null && grandparent.getNodeType() == IJSNodeTypes.FUNCTION) { DocumentationBlock docs = ((JSNode) grandparent).getDocumentation(); if (docs != null) { String name = identifierNode.getText(); int index = identifierNode.getIndex(); List<Tag> params = docs.getTags(TagType.PARAM); if (params != null && index < params.size()) { ParamTag param = (ParamTag) params.get(index); if (name.equals(param.getName())) { for (Type parameterType : param.getTypes()) { String type = parameterType.getName(); // Fix up type names as might be necessary type = JSTypeMapper.getInstance().getMappedType(type); this.addType(type); foundType = true; } } } } } // Use "Object" as parameter type if we didn't find types by other // means if (!foundType) { this.addType(JSTypeConstants.DEFAULT_PARAMETER_TYPE); } }
/** * @param parseResult * @param document * @return */ public IFormatterContainerNode build(IParseNode parseResult, FormatterDocument document) { this.document = document; final IFormatterContainerNode rootNode = new FormatterCSSRootNode(document); start(rootNode); IParseNode[] children = parseResult.getChildren(); addNodes(children); checkedPop(rootNode, document.getLength()); // Collect Off/On tags if (parseResult instanceof IParseRootNode) { setOffOnRegions( resolveOffOnRegions( (IParseRootNode) parseResult, document, CSSFormatterConstants.FORMATTER_OFF_ON_ENABLED, CSSFormatterConstants.FORMATTER_OFF, CSSFormatterConstants.FORMATTER_ON)); } return rootNode; }
/* * (non-Javadoc) * @see com.aptana.editor.js.parsing.ast.JSTreeWalker#visit(com.aptana.editor.js.parsing.ast.JSInvokeNode) */ @Override public void visit(JSInvokeNode node) { IParseNode child = node.getExpression(); if (child instanceof JSNode) { // TODO hang the "require" string as a constant somewhere! if (child instanceof JSIdentifierNode && "require".equals(child.getNameNode().getName())) // $NON-NLS-1$ { // it's a requires! JSArgumentsNode args = (JSArgumentsNode) node.getArguments(); IParseNode[] children = args.getChildren(); for (IParseNode arg : children) { if (arg instanceof JSStringNode) { JSStringNode string = (JSStringNode) arg; String text = string.getText(); // strip quotes TODO Use util method to strip quotes! if (text.startsWith("'") || text.startsWith("\"")) // $NON-NLS-1$ //$NON-NLS-2$ { text = text.substring(1, text.length() - 1); } // Handle resolving absolute versus relative module ids! URI resolved = _location.resolve(text); URI relative = _index.getRelativeDocumentPath(resolved); this.addType(relative.getPath() + ".exports"); // $NON-NLS-1$ } } } List<String> types = this.getTypes(child); // NOTE: This is a special case for functions used as a RHS of assignments or as part of a // property chain. // If the invocation returns undefined, we change that to Object. // TODO: As a refinement, we want to check that the function being called is not defined in // the current // scope if (types.isEmpty()) { IParseNode parent = node.getParent(); if (parent != null) { switch (parent.getNodeType()) { case IJSNodeTypes.ASSIGN: if (node.getIndex() == 1) { this.addType(JSTypeConstants.OBJECT_TYPE); } break; case IJSNodeTypes.GET_PROPERTY: this.addType(JSTypeConstants.OBJECT_TYPE); break; default: break; } } } for (String typeName : types) { if (JSTypeUtil.isFunctionPrefix(typeName)) { List<String> returnTypes = JSTypeUtil.getFunctionSignatureReturnTypeNames(typeName); for (String returnTypeName : returnTypes) { this.addType(returnTypeName); } } } } }