| /******************************************************************************* |
| * Copyright (c) 2010 xored software, Inc. |
| * |
| * 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: |
| * xored software, Inc. - initial API and Implementation (Alex Panchenko) |
| *******************************************************************************/ |
| package org.eclipse.dltk.javascript.internal.search; |
| |
| import java.util.List; |
| |
| import org.eclipse.dltk.compiler.CharOperation; |
| import org.eclipse.dltk.core.IMember; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.ISourceRange; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.search.SearchPattern; |
| import org.eclipse.dltk.core.search.matching2.AbstractMatchingPredicate; |
| import org.eclipse.dltk.core.search.matching2.IMatchingPredicate; |
| import org.eclipse.dltk.core.search.matching2.MatchLevel; |
| import org.eclipse.dltk.internal.core.search.matching.MethodDeclarationPattern; |
| import org.eclipse.dltk.internal.core.search.matching.MethodPattern; |
| import org.eclipse.dltk.javascript.ast.Expression; |
| import org.eclipse.dltk.javascript.typeinference.ReferenceLocation; |
| |
| @SuppressWarnings("restriction") |
| public class MethodPredicate extends AbstractMatchingPredicate<MatchingNode> { |
| |
| private final boolean declarations; |
| private final boolean references; |
| |
| private final ISourceModule module; |
| private final int nameStart; |
| private final int nameEnd; |
| |
| public MethodPredicate(MethodPattern pattern) { |
| this(pattern, pattern.selector, pattern.findDeclarations, |
| pattern.findReferences); |
| } |
| |
| public MethodPredicate(MethodDeclarationPattern pattern) { |
| this(pattern, pattern.simpleName, true, false); |
| } |
| |
| private MethodPredicate(SearchPattern pattern, char[] pat, |
| boolean declarations, boolean references) { |
| super(pattern, pat); |
| this.declarations = declarations; |
| this.references = references; |
| ISourceRange nameRange = null; |
| if (pattern.focus instanceof IMember) { |
| try { |
| nameRange = ((IMember) pattern.focus).getNameRange(); |
| } catch (ModelException e) { |
| } |
| } |
| |
| if (nameRange != null) { |
| nameStart = nameRange.getOffset(); |
| nameEnd = nameStart + nameRange.getLength(); |
| if (pattern.focus != null) |
| module = (ISourceModule) pattern.focus |
| .getAncestor(IModelElement.SOURCE_MODULE); |
| else |
| module = null; |
| } else { |
| nameStart = -1; |
| nameEnd = -1; |
| module = null; |
| } |
| } |
| |
| public MatchLevel match(MatchingNode node) { |
| if (node instanceof MethodDeclarationNode) { |
| if (!declarations) |
| return null; |
| final MethodDeclarationNode mNode = (MethodDeclarationNode) node; |
| if (nameStart != -1 && nameEnd != -1 && mNode.method != null) { |
| if (nameStart == mNode.sourceStart() |
| && nameEnd == mNode.sourceEnd() |
| && isSame(mNode.method.getLocation().getSourceModule())) { |
| return matchName(mNode.getName()); |
| } |
| } else { |
| return matchName(mNode.getName()); |
| } |
| } else if (node instanceof FieldDeclarationNode) { |
| if (!declarations) |
| return null; |
| final FieldDeclarationNode fNode = (FieldDeclarationNode) node; |
| if (nameStart != -1 && nameEnd != -1) { |
| if (nameStart == fNode.sourceStart() |
| && nameEnd == fNode.sourceEnd() && isSame(fNode.module)) { |
| return matchName(fNode.getName()); |
| } |
| } else { |
| return matchName(fNode.getName()); |
| } |
| } else if (node instanceof MethodReferenceNode) { |
| if (!references) |
| return null; |
| final MethodReferenceNode mNode = (MethodReferenceNode) node; |
| if (nameStart != -1 && nameEnd != -1) { |
| final ReferenceLocation location = mNode.location; |
| if (location != null) { |
| if (location.getNameStart() == nameStart |
| && location.getNameEnd() == nameEnd |
| && isSame(location.getSourceModule())) { |
| return matchName(mNode.node.getName(), |
| MatchLevel.ACCURATE_MATCH); |
| } |
| } else { |
| return matchName(mNode.node.getName()); |
| } |
| } else { |
| return matchName(mNode.node.getName(), |
| MatchLevel.INACCURATE_MATCH); |
| } |
| } else if (node instanceof FieldReferenceNode) { |
| if (!references) |
| return null; |
| // also test if the field does reference that function. |
| final FieldReferenceNode mNode = (FieldReferenceNode) node; |
| if (nameStart != -1 && nameEnd != -1) { |
| final ReferenceLocation location = mNode.location; |
| if (location != null) { |
| if (location.getNameStart() == nameStart |
| && location.getNameEnd() == nameEnd |
| && isSame(location.getSourceModule())) { |
| return matchName(mNode.node.getName(), |
| MatchLevel.ACCURATE_MATCH); |
| } |
| } else { |
| return matchName(mNode.node.getName()); |
| } |
| } else { |
| return matchName(mNode.node.getName(), |
| MatchLevel.INACCURATE_MATCH); |
| } |
| } else if (node instanceof LocalVariableReferenceNode) { |
| if (!references) |
| return null; |
| // also test if the field does reference that function. |
| final LocalVariableReferenceNode varNode = (LocalVariableReferenceNode) node; |
| if (nameStart != -1 && nameEnd != -1) { |
| final ReferenceLocation location = varNode.declarationLoc; |
| if (location != null) { |
| if (location.getNameStart() == nameStart |
| && location.getNameEnd() == nameEnd |
| && isSame(location.getSourceModule())) { |
| return matchName(varNode.node.getName(), |
| MatchLevel.ACCURATE_MATCH); |
| } |
| } else { |
| return matchName(varNode.node.getName()); |
| } |
| } else { |
| return matchName(varNode.node.getName(), |
| MatchLevel.INACCURATE_MATCH); |
| } |
| } else if (node instanceof LocalVariableDeclarationNode) { |
| if (!declarations) |
| return null; |
| final LocalVariableDeclarationNode varNode = (LocalVariableDeclarationNode) node; |
| if (varNode.node.sourceStart() == nameStart |
| && varNode.node.sourceEnd() == nameEnd |
| && isSame(varNode.module)) { |
| return matchName(varNode.node.getName(), MatchLevel.ACCURATE_MATCH); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public MatchLevel resolvePotentialMatch(MatchingNode node) { |
| if (nameStart != -1 && nameEnd != -1) { |
| if (node instanceof MemberReferenceNode) { |
| final MemberReferenceNode mNode = (MemberReferenceNode) node; |
| final ReferenceLocation location = mNode.location; |
| return location != null && location.getNameStart() == nameStart |
| && location.getNameEnd() == nameEnd |
| && isSame(location.getSourceModule()) ? MatchLevel.ACCURATE_MATCH |
| : null; |
| } else if (node instanceof MethodDeclarationNode) { |
| Expression exp = ((MethodDeclarationNode) node).node; |
| if (exp != null && exp.sourceStart() == nameStart |
| && exp.sourceEnd() == nameEnd |
| && isSame(((MethodDeclarationNode) node).method |
| .getLocation().getSourceModule())) { |
| return MatchLevel.ACCURATE_MATCH; |
| } |
| } |
| } |
| return super.resolvePotentialMatch(node); |
| } |
| |
| private boolean isSame(ISourceModule module) { |
| return module != null && module.equals(this.module); |
| } |
| |
| @Override |
| protected void collectToStringOptions(List<String> options) { |
| super.collectToStringOptions(options); |
| if (declarations) { |
| options.add("declarations"); |
| } |
| if (references) { |
| options.add("references"); |
| } |
| } |
| |
| @Override |
| public boolean contains(IMatchingPredicate<MatchingNode> predicate) { |
| if (predicate instanceof MethodPredicate) { |
| final MethodPredicate other = (MethodPredicate) predicate; |
| if (CharOperation.equals(namePattern, other.namePattern) |
| && (module != null && module.equals(other.module)) |
| && nameStart == other.nameStart && nameEnd == other.nameEnd |
| && (references || references == other.references) |
| && (declarations || declarations == other.declarations)) { |
| return true; |
| } |
| } |
| return super.contains(predicate); |
| } |
| |
| } |