/******************************************************************************* * Copyright (c) 2000, 2009 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.core.tests.model; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.wst.jsdt.core.*; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.search.*; import org.eclipse.wst.jsdt.internal.compiler.problem.AbortCompilationUnit; import org.eclipse.wst.jsdt.internal.core.PackageFragment; //import org.eclipse.wst.jsdt.internal.core.ResolvedSourceMethod; //import org.eclipse.wst.jsdt.internal.core.ResolvedSourceType; import org.eclipse.wst.jsdt.internal.core.SourceRefElement; import org.eclipse.wst.jsdt.internal.core.search.matching.PatternLocator; /** * Abstract class for Java Search tests. */ public class AbstractJavaSearchTests extends AbstractJavaModelTests implements IJavaScriptSearchConstants { public static List JAVA_SEARCH_SUITES = null; protected static IJavaScriptProject JAVA_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; // IJavaScriptUnit[] workingCopies; // boolean discard; /** * Collects results as a string. */ public static class JavaSearchResultCollector 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 showFlavors = 0; public int count = 0; public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException { count++; this.match = searchMatch; writeLine(); if (line != null) { 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(); IJavaScriptElement element = getElement(match); line = new StringBuffer(getPathString(resource, element)); if (this.showProject) { IProject project = element.getJavaScriptProject().getProject(); line.append(" [in "); line.append(project.getName()); line.append("]"); } IJavaScriptUnit unit = null; if (element instanceof IFunction) { line.append(" "); IFunction method = (IFunction)element; append(method); unit = method.getJavaScriptUnit(); } else if (element instanceof IType) { line.append(" "); IType type = (IType)element; append(type); unit = type.getJavaScriptUnit(); } else if (element instanceof IField) { line.append(" "); IField field = (IField)element; append(field); unit = field.getJavaScriptUnit(); } else if (element instanceof IInitializer) { line.append(" "); IInitializer initializer = (IInitializer)element; append(initializer); unit = initializer.getJavaScriptUnit(); } else if (element instanceof IPackageFragment) { line.append(" "); append((IPackageFragment)element); } else if (element instanceof ILocalVariable) { line.append(" "); ILocalVariable localVar = (ILocalVariable)element; IJavaScriptElement parent = localVar.getParent(); if (parent instanceof IInitializer) { IInitializer initializer = (IInitializer)parent; append(initializer); line.append("."); } else if (parent instanceof IFunction){ // IFunction IFunction method = (IFunction)parent; append(method); line.append("."); } line.append(localVar.getElementName()); unit = (IJavaScriptUnit)localVar.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT); } else if (element instanceof IImportDeclaration) { IImportDeclaration importDeclaration = (IImportDeclaration)element; unit = (IJavaScriptUnit)importDeclaration.getAncestor(IJavaScriptElement.JAVASCRIPT_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 (this.showFlavors > 0) { if (match instanceof MethodReferenceMatch) { MethodReferenceMatch methRef = (MethodReferenceMatch) match; if (methRef.isSuperInvocation() && showSuperInvocation()) { line.append(" SUPER INVOCATION"); } } } } catch (JavaScriptModelException e) { results.append("\n"); results.append(e.toString()); } } private boolean showSuperInvocation() { return (this.showFlavors & PatternLocator.SUPER_INVOCATION_FLAVOR) != 0; } protected void append(IField field) throws JavaScriptModelException { append(field.getDeclaringType()); line.append("."); line.append(field.getElementName()); } private void append(IInitializer initializer) throws JavaScriptModelException { append(initializer.getDeclaringType()); line.append("."); if (Flags.isStatic(initializer.getFlags())) { line.append("static "); } line.append("{}"); } private void append(IFunction method) throws JavaScriptModelException { if (!method.isConstructor() && method.getReturnType()!=null) { line.append(Signature.toString(method.getReturnType())); line.append(" "); } if (method.getDeclaringType()!=null) { append(method.getDeclaringType()); line.append("."); } if (!method.isConstructor()) { line.append(method.getElementName()); } line.append("("); String[] parameters = method.getParameterTypes(); boolean varargs = Flags.isVarargs(method.getFlags()); for (int i = 0, length=parameters.length; i<length; i++) { if (i < length - 1) { line.append(Signature.toString(parameters[i])); line.append(", "); //$NON-NLS-1$ } else if (varargs) { // remove array from signature String parameter = parameters[i].substring(1); line.append(Signature.toString(parameter)); line.append(" ..."); //$NON-NLS-1$ } else { line.append(Signature.toString(parameters[i])); } } line.append(")"); } private void append(IPackageFragment pkg) { line.append(pkg.getElementName()); } private void append(IType type) throws JavaScriptModelException { IJavaScriptElement parent = type.getParent(); boolean isLocal = false; switch (parent.getElementType()) { case IJavaScriptElement.JAVASCRIPT_UNIT: IPackageFragment pkg = type.getPackageFragment(); append(pkg); if (!pkg.getElementName().equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) { line.append("."); } break; case IJavaScriptElement.CLASS_FILE: IType declaringType = type.getDeclaringType(); if (declaringType != null) { append(type.getDeclaringType()); line.append("$"); } else { pkg = type.getPackageFragment(); append(pkg); if (!pkg.getElementName().equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) { line.append("."); } } break; case IJavaScriptElement.TYPE: append((IType)parent); line.append("$"); break; case IJavaScriptElement.FIELD: append((IField)parent); isLocal = true; break; case IJavaScriptElement.INITIALIZER: append((IInitializer)parent); isLocal = true; break; case IJavaScriptElement.METHOD: append((IFunction)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 IJavaScriptElement getElement(SearchMatch searchMatch) { return (IJavaScriptElement) searchMatch.getElement(); } protected String getPathString(IResource resource, IJavaScriptElement element) { String pathString; if (resource != null) { IPath path = resource.getProjectRelativePath(); if (path.segmentCount() == 0) { IJavaScriptElement root = element; while (root != null && !(root instanceof IPackageFragmentRoot)) { root = root.getParent(); } if (root != null) { IPackageFragmentRoot pkgFragmentRoot = (IPackageFragmentRoot)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, IJavaScriptElement element, IJavaScriptUnit unit) throws CoreException { char[] contents = CharOperation.NO_CHAR; if ("js".equals(resource.getFileExtension())) { IJavaScriptUnit cu = (IJavaScriptUnit)element.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT); if (cu != null && cu.isWorkingCopy()) { // working copy contents = unit.getBuffer().getCharacters(); } else { IFile file = ((IFile) resource); try { contents = new org.eclipse.wst.jsdt.internal.compiler.batch.CompilationUnit( null, file.getLocation().toFile().getPath(), file.getCharset()).getContents(); } catch(AbortCompilationUnit e) { // TODO (philippe) occured with a FileNotFoundException // ignore } } } return contents; } public String toString() { return results.toString(); } } static class TypeNameMatchCollector extends TypeNameMatchRequestor { List matches = new ArrayList(); public void acceptTypeNameMatch(TypeNameMatch match) { IType type = match.getType(); if (type != null) { this.matches.add(type); } } public int size() { return this.matches.size(); } private String toString(int kind) { int size = size(); if (size == 0) return ""; String[] strings = new String[size]; for (int i=0; i<size; i++) { IType type = (IType) this.matches.get(i); switch (kind) { case 1: // fully qualified name strings[i] = type.getFullyQualifiedName(); break; case 0: default: strings[i] = type.toString(); } } Arrays.sort(strings); StringBuffer buffer = new StringBuffer(); for (int i=0; i<size; i++) { if (i>0) buffer.append('\n'); buffer.append(strings[i]); } return buffer.toString(); } public String toString() { return toString(0); } public String toFullyQualifiedNamesString() { return toString(1); } } protected JavaSearchResultCollector resultCollector; public AbstractJavaSearchTests(String name) { this(name, 2); } public AbstractJavaSearchTests(String name, int tabs) { super(name, tabs); this.displayName = true; } /* (non-Javadoc) * @see org.eclipse.wst.jsdt.core.tests.model.AbstractJavaModelTests#assertSearchResults(java.lang.String, java.lang.Object) */ protected void assertSearchResults(String expected) { assertSearchResults(expected, resultCollector); } protected void assertSearchResults(String expected, JavaSearchResultCollector collector) { assertSearchResults("Unexpected search results", expected, collector); } protected void assertSearchResults(String message, String expected, JavaSearchResultCollector 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(displayString(actual, this.tabs)); 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 (JavaScriptModelException 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 ); } /* (non-Javadoc) * @see org.eclipse.wst.jsdt.core.tests.model.AbstractJavaModelTests#copyDirectory(java.io.File, java.io.File) */ 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"); File targetFile = new File(targetDir, ".project"); targetFile.createNewFile(); copy(sourceFile, targetFile); sourceFile = new File(sourceDir, ".classpath"); targetFile = new File(targetDir, ".classpath"); targetFile.createNewFile(); copy(sourceFile, targetFile); } } IJavaScriptSearchScope getJavaSearchScope() { return SearchEngine.createJavaSearchScope(new IJavaScriptProject[] {getJavaProject("JSSearch")}); } IJavaScriptSearchScope getJavaSearchScope15() { return SearchEngine.createJavaSearchScope(new IJavaScriptProject[] {getJavaProject("JavaSearch15")}); } IJavaScriptSearchScope getJavaSearchScope15(String packageName, boolean addSubpackages) throws JavaScriptModelException { if (packageName == null) return getJavaSearchScope15(); return getJavaSearchPackageScope("JavaSearch15", packageName, addSubpackages); } IJavaScriptSearchScope getJavaSearchPackageScope(String projectName, String packageName, boolean addSubpackages) throws JavaScriptModelException { IPackageFragment fragment = getPackageFragment(projectName, "src", packageName); if (fragment == null) return null; IJavaScriptElement[] searchPackages = null; if (addSubpackages) { // Create list of package with first found one List packages = new ArrayList(); packages.add(fragment); // Add all possible subpackages IJavaScriptElement[] children= ((IPackageFragmentRoot)fragment.getParent()).getChildren(); String[] names = ((PackageFragment)fragment).names; int namesLength = names.length; nextPackage: for (int i= 0, length = children.length; i < length; i++) { PackageFragment currentPackage = (PackageFragment) children[i]; String[] otherNames = currentPackage.names; 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 IJavaScriptElement[packages.size()]; packages.toArray(searchPackages); } else { searchPackages = new IJavaScriptElement[1]; searchPackages[0] = fragment; } return SearchEngine.createJavaSearchScope(searchPackages); } IJavaScriptSearchScope getJavaSearchCUScope(String projectName, String packageName, String cuName) throws JavaScriptModelException { IJavaScriptUnit cu = getCompilationUnit(projectName, "src", packageName, cuName); return SearchEngine.createJavaSearchScope(new IJavaScriptUnit[] { cu }); } protected void search(IJavaScriptElement element, int limitTo, IJavaScriptSearchScope scope) throws CoreException { search(element, limitTo, EXACT_RULE, scope, resultCollector); } IJavaScriptSearchScope getJavaSearchWorkingCopiesScope(IJavaScriptUnit workingCopy) throws JavaScriptModelException { return SearchEngine.createJavaSearchScope(new IJavaScriptUnit[] { workingCopy }); } IJavaScriptSearchScope getJavaSearchWorkingCopiesScope() throws JavaScriptModelException { return SearchEngine.createJavaSearchScope(this.workingCopies); } protected void search(IJavaScriptElement element, int limitTo, int matchRule, IJavaScriptSearchScope scope) throws CoreException { search(element, limitTo, matchRule, scope, resultCollector); } protected void search(IJavaScriptElement element, int limitTo, int matchRule, IJavaScriptSearchScope scope, SearchRequestor requestor) throws CoreException { SearchPattern pattern = SearchPattern.createPattern(element, limitTo, matchRule); assertNotNull("Pattern should not be null", pattern); new SearchEngine(workingCopies).search( pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, requestor, null ); } protected void search(SearchPattern searchPattern, IJavaScriptSearchScope 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, IJavaScriptSearchScope scope) throws CoreException { search(patternString, searchFor, limitTo, EXACT_RULE, scope, resultCollector); } protected void search(String patternString, int searchFor, int limitTo, int matchRule, IJavaScriptSearchScope scope) throws CoreException { search(patternString, searchFor, limitTo, matchRule, scope, resultCollector); } protected void search(String patternString, int searchFor, int limitTo, int matchRule, IJavaScriptSearchScope 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); assertNotNull("Pattern should not be null", pattern); new SearchEngine(workingCopies).search( pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, requestor, null); } protected void searchDeclarationsOfAccessedFields(IJavaScriptElement enclosingElement, SearchRequestor requestor) throws JavaScriptModelException { new SearchEngine().searchDeclarationsOfAccessedFields(enclosingElement, requestor, null); } protected void searchDeclarationsOfReferencedTypes(IJavaScriptElement enclosingElement, SearchRequestor requestor) throws JavaScriptModelException { new SearchEngine().searchDeclarationsOfReferencedTypes(enclosingElement, requestor, null); } protected void searchDeclarationsOfSentMessages(IJavaScriptElement enclosingElement, SearchRequestor requestor) throws JavaScriptModelException { new SearchEngine().searchDeclarationsOfSentMessages(enclosingElement, requestor, null); } protected void setUp () throws Exception { super.setUp(); this.resultCollector = new JavaSearchResultCollector(); } }