/** * @param locateNode * @return true if the given path indicates a trait */ private static boolean isTraitName(ASTNode locateNode) { assert locateNode != null; ASTNode parent = null; if (locateNode.getType() == ASTNode.CLASS_DECLARATION) { parent = locateNode; } else if (locateNode.getType() == ASTNode.IDENTIFIER) { parent = locateNode.getParent(); } else { return false; } if (parent.getType() == ASTNode.NAMESPACE_NAME) { locateNode = parent; parent = parent.getParent(); } final int parentType = parent.getType(); if (parentType == ASTNode.CLASS_DECLARATION || parentType == ASTNode.TRAIT_USE_STATEMENT || parentType == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) { if (parentType == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) { FullyQualifiedTraitMethodReference reference = (FullyQualifiedTraitMethodReference) parent; if (reference.getFunctionName() == locateNode) { return false; } } return true; } return false; }
public static boolean isGlobalConstant(ASTNode locateNode) { assert locateNode != null; // check if it is an identifier if (locateNode.getType() != ASTNode.IDENTIFIER) { return false; } ASTNode parent = locateNode.getParent(); if (parent.getType() != ASTNode.NAMESPACE_NAME) { return false; } final NamespaceName namespaceName = (NamespaceName) parent; parent = namespaceName.getParent(); if (parent.getType() == ASTNode.FUNCTION_NAME || parent.getType() == ASTNode.CLASS_NAME || parent.getType() == ASTNode.NAMESPACE || parent.getType() == ASTNode.USE_STATEMENT_PART || parent.getType() == ASTNode.TRAIT_USE_STATEMENT) { return false; } return true; }
/** * @param locateNode * @return true if the given path indicates a function */ private static boolean isFunction(ASTNode locateNode) { assert locateNode != null; ASTNode parent = null; Identifier targetIdentifier = null; if (locateNode.getType() == ASTNode.FUNCTION_DECLARATION) { parent = ((FunctionDeclaration) locateNode); targetIdentifier = ((FunctionDeclaration) locateNode).getFunctionName(); } else if (locateNode instanceof Identifier && !"define".equals(((Identifier) locateNode).getName())) { // $NON-NLS-1$ targetIdentifier = (Identifier) locateNode; parent = targetIdentifier.getParent(); if (parent != null && parent.getType() == ASTNode.NAMESPACE_NAME) { parent = targetIdentifier.getParent().getParent(); } } else { return false; } // check if it is a function if (parent == null || parent.getType() != ASTNode.FUNCTION_DECLARATION && parent.getType() != ASTNode.FUNCTION_NAME || parent.getParent().getType() == ASTNode.METHOD_DECLARATION || parent.getType() == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) { return false; } if (parent instanceof TraitAlias) { return false; } // check if it is a method final int type = parent.getParent().getType(); if (type == ASTNode.FUNCTION_INVOCATION) { final int parentParentType = parent.getParent().getParent().getType(); if (parentParentType == ASTNode.METHOD_DECLARATION || parentParentType == ASTNode.STATIC_METHOD_INVOCATION) { return false; } } else if (type == ASTNode.METHOD_DECLARATION) { return false; } return true; }
public ITypeBinding getDeclaringClass() { ASTNode parent = this.variableDeclaration.getParent(); while (parent != null && parent.getNodeType() != ASTNode.TYPE_DECLARATION) { parent = parent.getParent(); } if (parent != null) { return ((TypeDeclaration) parent).resolveBinding(); } return null; }
public IFunctionBinding getDeclaringMethod() { ASTNode parent = this.variableDeclaration.getParent(); while (parent != null && parent.getNodeType() != ASTNode.FUNCTION_DECLARATION) { parent = parent.getParent(); } if (parent != null) { return ((FunctionDeclaration) parent).resolveBinding(); } return null; }
/** * @param locateNode * @return true if the given path indicates a function */ private static boolean isClassName(ASTNode locateNode) { assert locateNode != null; ASTNode parent = null; if (locateNode.getType() == ASTNode.CLASS_DECLARATION || locateNode.getType() == ASTNode.INTERFACE_DECLARATION) { parent = locateNode; } else if (locateNode.getType() == ASTNode.IDENTIFIER) { parent = locateNode.getParent(); } else { return false; } if (parent.getType() == ASTNode.NAMESPACE_NAME) { locateNode = parent; parent = parent.getParent(); } if (parent instanceof TraitDeclaration) { return false; } final int parentType = parent.getType(); if (parentType == ASTNode.CLASS_NAME || parentType == ASTNode.CLASS_DECLARATION || parentType == ASTNode.INTERFACE_DECLARATION || parentType == ASTNode.CATCH_CLAUSE || parentType == ASTNode.FORMAL_PARAMETER || parentType == ASTNode.USE_STATEMENT_PART) { return true; } if (parentType == ASTNode.STATIC_METHOD_INVOCATION || parentType == ASTNode.STATIC_FIELD_ACCESS || parentType == ASTNode.STATIC_CONSTANT_ACCESS) { StaticDispatch staticDispatch = (StaticDispatch) parent; if (staticDispatch.getClassName() == locateNode) { return true; } } return false; }
public void test_addAll() { ASTNode parent = argumentList(); ArrayList<ASTNode> firstNodes = new ArrayList<ASTNode>(); ASTNode firstNode = booleanLiteral(true); ASTNode secondNode = booleanLiteral(false); firstNodes.add(firstNode); firstNodes.add(secondNode); NodeList<ASTNode> list = new NodeList<ASTNode>(parent); list.addAll(firstNodes); assertSize(2, list); assertSame(firstNode, list.get(0)); assertSame(secondNode, list.get(1)); assertSame(parent, firstNode.getParent()); assertSame(parent, secondNode.getParent()); ArrayList<ASTNode> secondNodes = new ArrayList<ASTNode>(); ASTNode thirdNode = booleanLiteral(true); ASTNode fourthNode = booleanLiteral(false); secondNodes.add(thirdNode); secondNodes.add(fourthNode); list.addAll(secondNodes); assertSize(4, list); assertSame(firstNode, list.get(0)); assertSame(secondNode, list.get(1)); assertSame(thirdNode, list.get(2)); assertSame(fourthNode, list.get(3)); assertSame(parent, firstNode.getParent()); assertSame(parent, secondNode.getParent()); assertSame(parent, thirdNode.getParent()); assertSame(parent, fourthNode.getParent()); }
private void markAsMoveOrCopyTarget(ASTNode node, ASTNode newChild) { if (this.cloneDepth == 0) { while (node != null && this.clonedNodes.containsKey(node)) { /* * A modified node cannot be considered as cloned any more. * we can't copy the original formatting/comments and at the same time modify the node. * * Workaround for https://bugs.eclipse.org/405699 is to remove such nodes from clonedNodes * and instead mark all children as cloned (or skip them if they are not in clonedNodes). */ ASTNode orig = (ASTNode) this.clonedNodes.remove(node); if (orig != null) { List properties = node.structuralPropertiesForType(); for (int i = 0; i < properties.size(); i++) { StructuralPropertyDescriptor property = (StructuralPropertyDescriptor) properties.get(i); Object child = node.getStructuralProperty(property); if (child instanceof ASTNode) { markAsMoveOrCopyTarget(node, (ASTNode) child); } else if (child instanceof List) { List children = (List) child; for (int j = 0; j < children.size(); j++) { ASTNode clonedChild = (ASTNode) children.get(j); markAsMoveOrCopyTarget(node, clonedChild); } } } } node = node.getParent(); } } ASTNode source = (ASTNode) this.clonedNodes.get(newChild); if (source != null) { if (this.cloneDepth == 0) { PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(source, RewriteEventStore.ORIGINAL); CopySourceInfo sourceInfo = this.eventStore.markAsCopySource( propertyLocation.getParent(), propertyLocation.getProperty(), source, false); this.nodeStore.markAsCopyTarget(newChild, sourceInfo); } } else if ((newChild.getFlags() & ASTNode.ORIGINAL) != 0) { PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChild, RewriteEventStore.ORIGINAL); CopySourceInfo sourceInfo = this.eventStore.markAsCopySource( propertyLocation.getParent(), propertyLocation.getProperty(), newChild, true); this.nodeStore.markAsCopyTarget(newChild, sourceInfo); } }
public void test_add() { ASTNode parent = argumentList(); ASTNode firstNode = booleanLiteral(true); ASTNode secondNode = booleanLiteral(false); NodeList<ASTNode> list = new NodeList<ASTNode>(parent); list.add(0, secondNode); list.add(0, firstNode); assertSize(2, list); assertSame(firstNode, list.get(0)); assertSame(secondNode, list.get(1)); assertSame(parent, firstNode.getParent()); assertSame(parent, secondNode.getParent()); ASTNode thirdNode = booleanLiteral(false); list.add(1, thirdNode); assertSize(3, list); assertSame(firstNode, list.get(0)); assertSame(thirdNode, list.get(1)); assertSame(secondNode, list.get(2)); assertSame(parent, firstNode.getParent()); assertSame(parent, secondNode.getParent()); assertSame(parent, thirdNode.getParent()); }
private static boolean isLocalVariable(ASTNode locateNode) { assert locateNode != null; Variable parent = null; // check if it is an identifier if (locateNode instanceof Identifier && ((Identifier) locateNode).getParent() instanceof Variable) { parent = (Variable) ((Identifier) locateNode).getParent(); } else if (locateNode.getType() == ASTNode.VARIABLE) { parent = (Variable) locateNode; } else { return false; } // check for not variables / or $this / or field declaration if (!parent.isDollared() || isThisVariable(parent) || parent.getType() == ASTNode.FIELD_DECLARATION) { return false; } // check for static variables if (parent.isDollared() && parent.getParent() != null && parent.getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) { return false; } // check for static array variables if (parent.isDollared() && parent.getParent() != null && parent.getParent().getType() == ASTNode.ARRAY_ACCESS && parent != ((ArrayAccess) parent.getParent()).getIndex() && parent.getParent().getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) { return false; } ASTNode node = parent; while (node != null) { final int type = node.getType(); if (type == ASTNode.FUNCTION_DECLARATION) { return true; } node = node.getParent(); } return false; }
public void endVisitNode(ASTNode node) { // Look if a child node is waiting for trailing comments computing ASTNode sibling = this.topSiblingParent == node ? (ASTNode) this.siblings[this.siblingPtr] : null; if (sibling != null) { try { storeTrailingComments( sibling, node.getEnd() - 1, true, this.parentLineRange[this.siblingPtr]); } catch (Exception ex) { // Give up extended ranges at this level if unexpected // exception happens... } } // Remove sibling if needed if (this.topSiblingParent != null /* not a CompilationUnit */ && this.topSiblingParent == node) { this.siblingPtr--; this.topSiblingParent = node.getParent(); } }
protected boolean apply(ASTNode node) { // Get default previous end ASTNode parent = node.getParent(); int previousEnd = parent.getStart(); // Look for sibling node ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null; if (sibling != null) { // Found one previous sibling, so compute its trailing comments // using current node start position try { previousEnd = storeTrailingComments( sibling, node.getStart(), false, this.parentLineRange[this.siblingPtr]); } catch (Exception ex) { // Give up extended ranges at this level if unexpected // exception happens... } } // Stop visit for malformed node (see bug // https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049) if (node.getType() == ASTNode.AST_ERROR) { return false; } // Compute leading comments for current node int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.document.getNumberOfLines()}; try { storeLeadingComments(node, previousEnd, previousLineRange); } catch (Exception ex) { // Give up extended ranges at this level if unexpected exception // happens... } // Store current node as waiting sibling for its parent if (this.topSiblingParent != parent) { if (this.siblings.length == ++this.siblingPtr) { System.arraycopy( this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr * 2], 0, this.siblingPtr); System.arraycopy( this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr * 2][], 0, this.siblingPtr); } if (this.topSiblingParent == null) { // node is a CompilationUnit this.parentLineRange[this.siblingPtr] = previousLineRange; } else { int parentStart = parent.getStart(); int firstLine = getLineNumber(parentStart, previousLineRange); int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange); if (this.parentLineRange[this.siblingPtr] == null) { this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine}; } else { int[] lineRange = this.parentLineRange[this.siblingPtr]; lineRange[0] = firstLine; lineRange[1] = lastLine; } } this.topSiblingParent = parent; } this.siblings[this.siblingPtr] = node; // We're always ok to visit sub-levels return true; }
/** * Search and store node trailing comments. Comments are searched in position range from node end * position to specified next start. If one or several comment are found, returns last comment end * position, otherwise returns node end position. * * <p>Starts to search for first comment after node end position and return if none was found... * * <p>When first comment is found after node, goes down in comment list until one of following * conditions becomes true: * * <ol> * <li>comment start is after next start * <li>there's other than white characters between current node and comment * <li>TODO there's more than 1 line between current node and comment * </ol> * * If at least potential comments have been found, then all of them has to be separated from * following node. So, remove all comments which do not verify this assumption. Note that this * verification is not applicable on last node. * * <p>If finally there's still trailing comments, then stores indexes of the first and last one in * trailing comments table. */ int storeTrailingComments(ASTNode node, int nextStart, boolean lastChild, int[] parentLineRange) { // Init extended position int nodeEnd = node.getEnd() - 1; if (nodeEnd == nextStart) { // special case for last child of its parent if (++this.trailingPtr == 0) { this.trailingNodes = new ASTNode[STORAGE_INCREMENT]; this.trailingIndexes = new long[STORAGE_INCREMENT]; this.lastTrailingPtr = -1; } else if (this.trailingPtr == this.trailingNodes.length) { int newLength = (this.trailingPtr * 3 / 2) + STORAGE_INCREMENT; System.arraycopy( this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr); System.arraycopy( this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr); } this.trailingNodes[this.trailingPtr] = node; this.trailingIndexes[this.trailingPtr] = -1; return nodeEnd; } int extended = nodeEnd; // Get line number int nodeEndLine = getLineNumber(nodeEnd, parentLineRange); // Find comments range index int idx = getCommentIndex(0, nodeEnd, 1); if (idx == -1) { return nodeEnd; } // Look after potential comments int startIdx = idx; int endIdx = -1; int length = this.comments.length; int commentStart = extended + 1; int previousEnd = nodeEnd + 1; int sameLineIdx = -1; while (idx < length && commentStart < nextStart) { // get comment and leave if next starting position has been reached Comment comment = this.comments[idx]; commentStart = comment.getStart(); // verify that there's nothing else than white spaces between // node/comments if (commentStart >= nextStart) { // stop search on condition 1) break; } else if (previousEnd < commentStart) { try { resetTo(previousEnd, commentStart); this.scanner.next_token(); String token = this.scanner.yytext(); if (token != null && token.trim().length() > 0) { // stop search on condition 2) // if first index fails, then there's no extended // position in fact... if (idx == startIdx) { return nodeEnd; } // otherwise we get the last index of trailing comment // => break break; } } catch (Exception e) { // Should not happen, but return no extended position... assert false; return nodeEnd; } } // Store index if we're on the same line than node end int commentLine = getLineNumber(commentStart, parentLineRange); if (commentLine == nodeEndLine) { sameLineIdx = idx; } // Store previous infos previousEnd = commentStart + comment.getLength(); endIdx = idx++; } if (endIdx != -1) { // Verify that following node start is separated if (!lastChild) { int nextLine = getLineNumber(nextStart, parentLineRange); int previousLine = getLineNumber(previousEnd, parentLineRange); if ((nextLine - previousLine) <= 1) { if (sameLineIdx == -1) return nodeEnd; endIdx = sameLineIdx; } } // Store trailing comments indexes if (++this.trailingPtr == 0) { this.trailingNodes = new ASTNode[STORAGE_INCREMENT]; this.trailingIndexes = new long[STORAGE_INCREMENT]; this.lastTrailingPtr = -1; } else if (this.trailingPtr == this.trailingNodes.length) { int newLength = (this.trailingPtr * 3 / 2) + STORAGE_INCREMENT; System.arraycopy( this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr); System.arraycopy( this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr); } this.trailingNodes[this.trailingPtr] = node; long nodeRange = (((long) startIdx) << 32) + endIdx; this.trailingIndexes[this.trailingPtr] = nodeRange; // Compute new extended end extended = this.comments[endIdx].getEnd() - 1; // Look for children unresolved extended end ASTNode previousNode = node; int ptr = this.trailingPtr - 1; // children extended end were stored // before while (ptr >= 0) { long range = this.trailingIndexes[ptr]; if (range != -1) break; // there's no more unresolved nodes ASTNode unresolved = this.trailingNodes[ptr]; if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy this.trailingIndexes[ptr] = nodeRange; previousNode = unresolved; ptr--; // get previous node } // Remove remaining unresolved nodes if (ptr > this.lastTrailingPtr) { int offset = ptr - this.lastTrailingPtr; for (int i = ptr + 1; i <= this.trailingPtr; i++) { this.trailingNodes[i - offset] = this.trailingNodes[i]; this.trailingIndexes[i - offset] = this.trailingIndexes[i]; } this.trailingPtr -= offset; } this.lastTrailingPtr = this.trailingPtr; } return extended; }
/** * Identifies a dispatch usage * * @param locateNode */ private static boolean isDispatch(ASTNode locateNode) { assert locateNode != null; ASTNode parent = null; // check if it is an identifier final int type = locateNode.getType(); if (locateNode instanceof Identifier && ((Identifier) locateNode).getParent() instanceof Variable) { parent = (Variable) ((Identifier) locateNode).getParent(); parent = parent.getParent(); } else if (type == ASTNode.SINGLE_FIELD_DECLARATION || type == ASTNode.FIELD_DECLARATION || type == ASTNode.METHOD_DECLARATION) { parent = locateNode; } else { parent = locateNode.getParent(); } if (parent instanceof TraitAlias) { // TraitAlias ta = (TraitAlias) parent; // return locateNode == ta.getTraitMethod(); return true; } // check if it is a method declaration if (parent.getType() == ASTNode.FUNCTION_DECLARATION) { // check if it is a method declaration if (parent.getParent() != null) { parent = parent.getParent(); if (parent.getType() == ASTNode.METHOD_DECLARATION) { return true; } } return false; } if (parent.getType() == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) { FullyQualifiedTraitMethodReference reference = (FullyQualifiedTraitMethodReference) parent; if (reference.getFunctionName() == locateNode) { return true; } return false; } if (parent.getType() == ASTNode.SINGLE_FIELD_DECLARATION) { // check for $this variable if (parent.getParent().getType() == ASTNode.FIELD_DECLARATION || parent.getParent().getType() == ASTNode.SINGLE_FIELD_DECLARATION) { return true; } } if (parent.getType() == ASTNode.FIELD_DECLARATION || parent.getType() == ASTNode.METHOD_DECLARATION) { return true; } if (parent.getType() == ASTNode.VARIABLE) { if (parent.getParent().getType() == ASTNode.FIELD_DECLARATION || parent.getParent().getType() == ASTNode.SINGLE_FIELD_DECLARATION) { return true; } } if (parent.getType() == ASTNode.CONSTANT_DECLARATION) return true; // check if it is a dispatch while (parent != null) { if (parent instanceof Dispatch || parent instanceof StaticDispatch) { return true; } parent = parent.getParent(); } return false; }
public JavaRefactoringDescriptor buildEclipseDescriptor() throws Exception { System.err.println("[eclipse-rename] Building descriptor..."); IJavaElement element = location.getIJavaElement(); String kind = getRenameKind(element); // [1] BUGFIX was needed: The scripting interface didn't allow VariableDeclarationFragments as // IJavaElements // and thus had to be extended // [2] WORKAROUND for scripting interface bug (see below) if (kind.equals(IJavaRefactorings.RENAME_METHOD)) { IMethod m = (IMethod) element; if (m.isConstructor()) { // Rename the type instead (as the UI would do-- the scripting interface will only rename // the constructor, which is broken) kind = IJavaRefactorings.RENAME_TYPE; element = m.getDeclaringType(); } } System.err.println("[eclipse-rename] Kind = " + kind + ", element = " + element); // [3] Don't test for package fragments now if (kind.equals(IJavaRefactorings.RENAME_PACKAGE)) return null; // don't bother with this now if (element == null) { System.err.println("!!! ABORT: No IJavaElement to represent location"); throw new RuntimeException("!!! ABORT: No IJavaElement for location"); } if (element instanceof ILocalVariable) { System.err.println("element is of type " + element.getClass()); final ILocalVariable fLocalVariable = (ILocalVariable) element; final ISourceRange sourceRange = fLocalVariable.getNameRange(); final CompilationUnit fCompilationUnitNode = location.getCompilationUnit(); ASTNode name = NodeFinder.perform(fCompilationUnitNode, sourceRange); System.err.println("node is of type " + name.getClass()); if (name == null) System.err.println("!!! ILV doesn't have associated name!"); if (name.getParent() instanceof VariableDeclaration) System.err.println("ILV has parent : " + (VariableDeclaration) name.getParent()); else System.err.println( "!!! ILV doesn't have var declaration parent, instead " + name.getParent().getClass()); } System.err.println("Trying to rename a " + kind + ": " + element); if (element instanceof SimpleName) System.err.println(" Name = '" + ((SimpleName) element).getIdentifier() + "'"); if (kind.equals(IJavaRefactorings.RENAME_TYPE)) { System.err.println("(Possibly need a new launch configuration)"); tproject.renameClass((IType) element, new_name); } final RenameJavaElementDescriptor descriptor = (RenameJavaElementDescriptor) getDescriptor(kind); descriptor.setJavaElement(element); descriptor.setNewName(this.new_name); if (element.getElementType() == IJavaElement.TYPE || element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) descriptor.setUpdateQualifiedNames(true); else descriptor.setUpdateQualifiedNames(false); descriptor.setUpdateReferences(true); descriptor.setDeprecateDelegate(false); descriptor.setRenameGetters(false); descriptor.setRenameSetters(false); descriptor.setKeepOriginal(false); descriptor.setUpdateHierarchy(false); descriptor.setUpdateSimilarDeclarations(false); // [3] Fix: Eclipse will complain if the transformation is a no-op, but we don't want that: if (element.getElementName().equals(this.new_name)) throw new NOPException(); System.err.println("[eclipse-rename] Computed descriptor."); return descriptor; }
private static boolean checkGlobalIdentifier(ASTNode locateNode) { // check if it is a GLOBALS['a'] direction if (locateNode.getType() == ASTNode.SCALAR) { Scalar scalar = (Scalar) locateNode; return checkGLOBALS(scalar); } // check if it is an identifier if (locateNode.getType() != ASTNode.IDENTIFIER) { return false; } final Identifier targetIdentifier = ((Identifier) locateNode); ASTNode parent = locateNode.getParent(); if (parent == null || parent.getType() != ASTNode.VARIABLE) { return false; } final Variable variable = (Variable) parent; // if it is not a dollared variable - it is not a global one if (!variable.isDollared() || variable.getParent().getType() == ASTNode.FIELD_DECLARATION) { return false; } // ignore static memeber call if (parent.getParent().getType() == ASTNode.STATIC_FIELD_ACCESS) { final StaticFieldAccess staticFieldAccess = (StaticFieldAccess) parent.getParent(); if (staticFieldAccess.getMember() == variable) { return false; } } if (parent.getParent().getLocationInParent() == FieldsDeclaration.FIELDS_PROPERTY) { return false; } // check if declared global in function while (parent != null) { // if the variable was used inside a function if (parent.getType() == ASTNode.FUNCTION_DECLARATION) { // global declaration detection final int end = parent.getEnd(); class GlobalSeacher extends ApplyAll { public int offset = end; public boolean apply(ASTNode node) { if (offset != end) { return false; } if (node.getType() == ASTNode.GLOBAL_STATEMENT) { GlobalStatement globalStatement = (GlobalStatement) node; if (checkGlobal(targetIdentifier, globalStatement)) { offset = globalStatement.getStart(); } } return true; } } GlobalSeacher searchGlobal = new GlobalSeacher(); parent.accept(searchGlobal); return searchGlobal.offset <= targetIdentifier.getStart(); } parent = parent.getParent(); } return true; }
/** * Identifies a constant use * * @param locateNode * @return */ private static boolean isConstant(ASTNode locateNode) { assert locateNode != null; Scalar scalar = null; // check if it is an identifier if (locateNode.getType() != ASTNode.SCALAR) { ASTNode parent = locateNode.getParent(); ASTNode node = null; // php 5.3, the parent is NamespaceName if (parent instanceof NamespaceName) { node = parent.getParent().getParent(); } else { // non-php 5.3 node = parent.getParent(); } // check if the node is 'define' if ((locateNode instanceof Identifier) && "define".equals(((Identifier) locateNode).getName()) // $NON-NLS-1$ && node instanceof FunctionInvocation) { FunctionInvocation inv = (FunctionInvocation) node; List<Expression> parameters = inv.parameters(); if (parameters != null && parameters.size() > 0) { Expression param = parameters.get(0); if (param instanceof Scalar) { scalar = (Scalar) param; } else { return false; } } } else { return false; } } else { scalar = (Scalar) locateNode; } // if it is not a dollared variable - it is not a global one if (scalar == null || scalar.getScalarType() != Scalar.TYPE_STRING || scalar.getStringValue() == null) { return false; } final int length = scalar.getStringValue().length() - 1; final char charAtBegining = scalar.getStringValue().charAt(0); final char charAtEnd = scalar.getStringValue().charAt(length); if (!detectString(charAtEnd) && !detectString(charAtBegining)) { return true; } // check if it is part of define ASTNode previous = locateNode.getParent(); if (previous instanceof NamespaceName) { previous = previous.getParent(); } if (previous.getType() == ASTNode.FUNCTION_NAME) { previous = previous.getParent(); } if (previous.getType() != ASTNode.FUNCTION_INVOCATION) { return false; } final FunctionInvocation functionInvocation = (FunctionInvocation) previous; if (!(functionInvocation.getFunctionName().getName() instanceof Identifier)) { return false; } final Identifier identifier = (Identifier) functionInvocation.getFunctionName().getName(); return "define".equalsIgnoreCase(identifier.getName()) || "constant".equalsIgnoreCase(identifier.getName()); // $NON-NLS-1$ //$NON-NLS-2$ }