/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ package org.eclipse.dltk.core.tests.model; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.dltk.compiler.CharOperation; import org.eclipse.dltk.core.DLTKLanguageManager; import org.eclipse.dltk.core.IField; import org.eclipse.dltk.core.IMethod; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IProjectFragment; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.IScriptProjectFilenames; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.IType; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.core.search.IDLTKSearchConstants; import org.eclipse.dltk.core.search.IDLTKSearchScope; import org.eclipse.dltk.core.search.MethodReferenceMatch; import org.eclipse.dltk.core.search.SearchEngine; import org.eclipse.dltk.core.search.SearchMatch; import org.eclipse.dltk.core.search.SearchParticipant; import org.eclipse.dltk.core.search.SearchPattern; import org.eclipse.dltk.core.search.SearchRequestor; import org.eclipse.dltk.internal.core.ScriptFolder; import org.eclipse.dltk.internal.core.SourceRefElement; import org.eclipse.dltk.internal.core.util.Util; /** * Abstract class for Script Search tests. */ public class AbstractDLTKSearchTests extends AbstractModelTests implements IDLTKSearchConstants, IScriptProjectFilenames { public static List<?> JAVA_SEARCH_SUITES = null; protected IScriptProject SCRIPT_PROJECT; protected static boolean COPY_DIRS = true; protected static int EXACT_RULE = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE; protected static int EQUIVALENT_RULE = EXACT_RULE | SearchPattern.R_EQUIVALENT_MATCH; protected static int ERASURE_RULE = EXACT_RULE | SearchPattern.R_ERASURE_MATCH; protected static int RAW_RULE = EXACT_RULE | SearchPattern.R_ERASURE_MATCH | SearchPattern.R_EQUIVALENT_MATCH; // ISourceModule[] workingCopies; // boolean discard; /** * Collects results as a string. */ public static class DLTKSearchResultCollector extends SearchRequestor { protected SearchMatch match; public StringBuffer results = new StringBuffer(), line; public boolean showAccuracy; public boolean showContext; public boolean showRule; public boolean showInsideDoc; public boolean showPotential = true; public boolean showProject; public boolean showSynthetic; public int count = 0; @Override public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException { count++; this.match = searchMatch; writeLine(); writeLineToResult(); } protected void writeLineToResult() { if (match.getAccuracy() == SearchMatch.A_ACCURATE || showPotential) { if (results.length() > 0) results.append("\n"); results.append(line); } } protected void writeLine() throws CoreException { try { IResource resource = match.getResource(); IModelElement element = getElement(match); line = new StringBuffer(getPathString(resource, element)); if (this.showProject) { IProject project = element.getScriptProject().getProject(); line.append(" [in "); line.append(project.getName()); line.append("]"); } ISourceModule unit = null; if (element instanceof IMethod) { line.append(" "); IMethod method = (IMethod) element; append(method); unit = method.getSourceModule(); } else if (element instanceof IType) { line.append(" "); IType type = (IType) element; append(type); unit = type.getSourceModule(); } else if (element instanceof IField) { line.append(" "); IField field = (IField) element; append(field); unit = field.getSourceModule(); } else if (element instanceof IScriptFolder) { line.append(" "); append((IScriptFolder) element); } // else if (element instanceof IImportDeclaration) { // IImportDeclaration importDeclaration = // (IImportDeclaration)element; // unit = // (ISourceModule)importDeclaration.getAncestor(IModelElement.COMPILATION_UNIT); // } else if (element instanceof IPackageDeclaration) { // IPackageDeclaration packageDeclaration = // (IPackageDeclaration)element; // unit = // (ISourceModule)packageDeclaration.getAncestor(IModelElement.COMPILATION_UNIT); // } if (resource instanceof IFile) { char[] contents = getSource(resource, element, unit); int start = match.getOffset(); int end = start + match.getLength(); if (start == -1 || (contents != null && contents.length > 0)) { // retrieving // attached // source // not // implemented // here line.append(" ["); if (start > -1) { if (this.showContext) { int lineStart1 = CharOperation.lastIndexOf('\n', contents, 0, start); int lineStart2 = CharOperation.lastIndexOf('\r', contents, 0, start); int lineStart = Math.max(lineStart1, lineStart2) + 1; line.append(CharOperation.subarray(contents, lineStart, start)); line.append("<"); } line.append(CharOperation.subarray(contents, start, end)); if (this.showContext) { line.append(">"); int lineEnd1 = CharOperation.indexOf('\n', contents, end); int lineEnd2 = CharOperation.indexOf('\r', contents, end); int lineEnd = lineEnd1 > 0 && lineEnd2 > 0 ? Math.min(lineEnd1, lineEnd2) : Math.max(lineEnd1, lineEnd2); if (lineEnd == -1) lineEnd = contents.length; line.append(CharOperation.subarray(contents, end, lineEnd)); } } else { line.append("No source"); } line.append("]"); } } if (this.showAccuracy) { line.append(" "); if (match.getAccuracy() == SearchMatch.A_ACCURATE) { if (this.showRule) { if (match.isExact()) { line.append("EXACT_"); } else if (match.isEquivalent()) { line.append("EQUIVALENT_"); } else if (match.isErasure()) { line.append("ERASURE_"); } else { line.append("INVALID_RULE_"); } if (match.isRaw()) { line.append("RAW_"); } } else { line.append("EXACT_"); } line.append("MATCH"); } else { line.append("POTENTIAL_MATCH"); } } if (this.showInsideDoc) { line.append(" "); if (match.isInsideDocComment()) { line.append("INSIDE_JAVADOC"); } else { line.append("OUTSIDE_JAVADOC"); } } if (this.showSynthetic) { if (match instanceof MethodReferenceMatch) { MethodReferenceMatch methRef = (MethodReferenceMatch) match; if (methRef.isSynthetic()) { line.append(" SYNTHETIC"); } } } } catch (ModelException e) { results.append("\n"); results.append(e.toString()); } } protected void append(IField field) throws ModelException { IType type = field.getDeclaringType(); if (type != null) { append(type); line.append("$"); } line.append(field.getElementName()); } private void append(IMethod method) throws ModelException { if (!method.isConstructor()) { // line.append(Signature.toString(method.getReturnType())); line.append(" "); } append(method.getDeclaringType()); if (!method.isConstructor()) { line.append("$"); line.append(method.getElementName()); } line.append("("); String[] parameters = method.getParameterNames(); for (int i = 0, length = parameters.length; i < length; i++) { if (i < length - 1) { // line.append(Signature.toString(parameters[i])); line.append(parameters[i]); line.append(", "); //$NON-NLS-1$ } else { // line.append(Signature.toString(parameters[i])); line.append(parameters[i]); } } line.append(")"); } private void append(IScriptFolder pkg) { line.append(pkg.getElementName()); } private void append(IType type) throws ModelException { if (type == null) { return; } IModelElement parent = type.getParent(); boolean isLocal = false; switch (parent.getElementType()) { case IModelElement.SOURCE_MODULE: IScriptFolder pkg = type.getScriptFolder(); append(pkg); if (!pkg.getElementName() .equals(IScriptFolder.DEFAULT_FOLDER_NAME)) { line.append(IScriptFolder.PACKAGE_DELIMITER); } break; case IModelElement.TYPE: append((IType) parent); line.append("$"); break; case IModelElement.FIELD: append((IField) parent); isLocal = true; break; case IModelElement.METHOD: append((IMethod) parent); isLocal = true; break; } if (isLocal) { line.append(":"); } String typeName = type.getElementName(); if (typeName.length() == 0) { line.append("<anonymous>"); } else { line.append(typeName); } if (isLocal) { line.append("#"); line.append(((SourceRefElement) type).occurrenceCount); } } protected IModelElement getElement(SearchMatch searchMatch) { return (IModelElement) searchMatch.getElement(); } protected String getPathString(IResource resource, IModelElement element) { String pathString; if (resource != null) { IPath path = resource.getProjectRelativePath(); if (path.segmentCount() == 0) { IModelElement root = element; while (root != null && !(root instanceof IProjectFragment)) { root = root.getParent(); } if (root != null) { IProjectFragment pkgFragmentRoot = (IProjectFragment) root; if (pkgFragmentRoot.isExternal()) { pathString = pkgFragmentRoot.getPath().toOSString(); } else { pathString = pkgFragmentRoot.getPath().toString(); } } else { pathString = ""; } } else { pathString = path.toString(); } } else { pathString = element.getPath().toString(); } return pathString; } protected char[] getSource(IResource resource, IModelElement element, ISourceModule unit) throws CoreException { char[] contents = CharOperation.NO_CHAR; if (Util.isValidSourceModule(resource) && element != null) { ISourceModule cu = (ISourceModule) element .getAncestor(IModelElement.SOURCE_MODULE); if (cu != null && cu.isWorkingCopy()) { // working copy contents = unit.getBuffer().getCharacters(); } } return contents; } @Override public String toString() { return results.toString(); } } protected DLTKSearchResultCollector resultCollector; public AbstractDLTKSearchTests(String pluginName, String name) { this(pluginName, name, 2); } public AbstractDLTKSearchTests(String pluginName, String name, int tabs) { super(pluginName, name); this.displayName = true; this.tabs = tabs; } protected void assertSearchResults(String expected) { assertSearchResults(expected, resultCollector); } protected void assertSearchResults(String expected, DLTKSearchResultCollector collector) { assertSearchResults("Unexpected search results", expected, collector); } protected void assertSearchResults(String message, String expected, DLTKSearchResultCollector collector) { String actual = collector.toString(); if (!expected.equals(actual)) { if (this.displayName) { System.out.print(getName()); System.out.print(" got "); if (collector.count == 0) System.out.println("no result!"); else { System.out.print(collector.count); System.out.print(" result"); if (collector.count == 1) System.out.println(":"); else System.out.println("s:"); } } if (!displayName || collector.count > 0) { System.out.print(actual); System.out.println(this.endChar); } if (this.workingCopies != null) { int length = this.workingCopies.length; String[] sources = new String[length * 2]; for (int i = 0; i < length; i++) { sources[i * 2] = this.workingCopies[i].getPath().toString(); try { sources[i * 2 + 1] = this.workingCopies[i].getSource(); } catch (ModelException e) { // ignore } } System.out.println( "--------------------------------------------------------------------------------"); for (int i = 0; i < length; i += 2) { System.out.println(sources[i]); System.out.println(sources[i + 1]); } } } assertEquals(message, expected, actual); } @Override protected void copyDirectory(File sourceDir, File targetDir) throws IOException { if (COPY_DIRS) { super.copyDirectory(sourceDir, targetDir); } else { targetDir.mkdirs(); File sourceFile = new File(sourceDir, PROJECT_FILENAME); File targetFile = new File(targetDir, PROJECT_FILENAME); targetFile.createNewFile(); copy(sourceFile, targetFile); sourceFile = new File(sourceDir, BUILDPATH_FILENAME); targetFile = new File(targetDir, BUILDPATH_FILENAME); targetFile.createNewFile(); copy(sourceFile, targetFile); } } protected IDLTKSearchScope getSearchScope(String project) { return SearchEngine.createSearchScope(getScriptProject(project)); } protected IDLTKSearchScope getSearchScope(IModelElement element) { return SearchEngine.createSearchScope(element); } protected IDLTKSearchScope getScriptSearchPackageScope(String projectName, String packageName, boolean addSubpackages) throws ModelException { IScriptFolder fragment = getScriptFolder(projectName, "src", new Path(packageName)); if (fragment == null) return null; IModelElement[] searchPackages = null; if (addSubpackages) { // Create list of package with first found one List<IScriptFolder> packages = new ArrayList<>(); packages.add(fragment); // Add all possible subpackages IModelElement[] children = ((IProjectFragment) fragment.getParent()) .getChildren(); String[] names = ((ScriptFolder) fragment).getRelativePath() .segments(); int namesLength = names.length; nextPackage: for (int i = 0, length = children.length; i < length; i++) { ScriptFolder currentPackage = (ScriptFolder) children[i]; String[] otherNames = currentPackage.getRelativePath() .segments(); if (otherNames.length <= namesLength) continue nextPackage; for (int j = 0; j < namesLength; j++) { if (!names[j].equals(otherNames[j])) continue nextPackage; } packages.add(currentPackage); } searchPackages = new IModelElement[packages.size()]; packages.toArray(searchPackages); } else { searchPackages = new IModelElement[1]; searchPackages[0] = fragment; } return SearchEngine.createSearchScope(searchPackages, DLTKLanguageManager .getLanguageToolkit(getScriptProject(projectName))); } IDLTKSearchScope getScriptSearchCUScope(String projectName, String packageName, String cuName) throws ModelException { ISourceModule cu = getSourceModule(projectName, "src", new Path(packageName).append(cuName)); return SearchEngine.createSearchScope(cu); } protected void search(IModelElement element, int limitTo, IDLTKSearchScope scope) throws CoreException { search(element, limitTo, EXACT_RULE, scope, resultCollector); } IDLTKSearchScope getSearchWorkingCopiesScope(ISourceModule workingCopy) throws ModelException { return SearchEngine.createSearchScope(workingCopy); } // IDLTKSearchScope getSearchWorkingCopiesScope() throws ModelException { // return SearchEngine.createSearchScope(this.workingCopies); // } protected void search(IModelElement element, int limitTo, int matchRule, IDLTKSearchScope scope) throws CoreException { search(element, limitTo, matchRule, scope, resultCollector); } protected void search(IModelElement element, int limitTo, int matchRule, IDLTKSearchScope scope, SearchRequestor requestor) throws CoreException { SearchPattern pattern = SearchPattern.createPattern(element, limitTo, matchRule, scope.getLanguageToolkit()); assertNotNull("Pattern should not be null", pattern); new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, requestor, null); } protected void search(SearchPattern searchPattern, IDLTKSearchScope scope, SearchRequestor requestor) throws CoreException { new SearchEngine().search(searchPattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, requestor, null); } protected void search(String patternString, int searchFor, int limitTo, IDLTKSearchScope scope) throws CoreException { search(patternString, searchFor, limitTo, EXACT_RULE, scope, resultCollector); } protected void search(String patternString, int searchFor, int limitTo, int matchRule, IDLTKSearchScope scope) throws CoreException { search(patternString, searchFor, limitTo, matchRule, scope, resultCollector); } protected void search(String patternString, int searchFor, int limitTo, int matchRule, IDLTKSearchScope scope, SearchRequestor requestor) throws CoreException { if (patternString.indexOf('*') != -1 || patternString.indexOf('?') != -1) { matchRule |= SearchPattern.R_PATTERN_MATCH; } SearchPattern pattern = SearchPattern.createPattern(patternString, searchFor, limitTo, matchRule, scope.getLanguageToolkit()); assertNotNull("Pattern should not be null", pattern); new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, requestor, null); } // Search for sources only. protected List<?> searchSourceOnly(IModelElement element, int limitTo, int matchRule, IDLTKSearchScope scope) throws CoreException { SearchPattern pattern = SearchPattern.createPattern(element, limitTo, matchRule, scope.getLanguageToolkit()); assertNotNull("Pattern should not be null", pattern); return new SearchEngine().searchSourceOnly(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, null); } protected List<?> searchSourceOnly(SearchPattern searchPattern, IDLTKSearchScope scope) throws CoreException { return new SearchEngine().searchSourceOnly(searchPattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, null); } protected List<?> searchSourceOnly(String patternString, int searchFor, int limitTo, IDLTKSearchScope scope) throws CoreException { return searchSourceOnly(patternString, searchFor, limitTo, EXACT_RULE, scope); } protected List<?> searchSourceOnly(String patternString, int searchFor, int limitTo, int matchRule, IDLTKSearchScope scope) throws CoreException { if (patternString.indexOf('*') != -1 || patternString.indexOf('?') != -1) { matchRule |= SearchPattern.R_PATTERN_MATCH; } SearchPattern pattern = SearchPattern.createPattern(patternString, searchFor, limitTo, matchRule, scope.getLanguageToolkit()); assertNotNull("Pattern should not be null", pattern); return new SearchEngine().searchSourceOnly(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, null); } // / protected void searchDeclarationsOfAccessedFields( IModelElement enclosingElement, SearchRequestor requestor) throws ModelException { new SearchEngine().searchDeclarationsOfAccessedFields(enclosingElement, requestor, null); } protected void searchDeclarationsOfReferencedTypes( IModelElement enclosingElement, SearchRequestor requestor) throws ModelException { new SearchEngine().searchDeclarationsOfReferencedTypes(enclosingElement, requestor, null); } protected void searchDeclarationsOfSentMessages( IModelElement enclosingElement, SearchRequestor requestor) throws ModelException { new SearchEngine().searchDeclarationsOfSentMessages(enclosingElement, requestor, null); } @Override protected void setUp() throws Exception { super.setUp(); this.resultCollector = new DLTKSearchResultCollector(); } }