001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.core.search.matching;
011:
012: import org.eclipse.core.resources.IResource;
013: import org.eclipse.jdt.core.*;
014: import org.eclipse.jdt.core.compiler.CharOperation;
015: import org.eclipse.jdt.core.search.SearchDocument;
016: import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
017: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
018: import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
019: import org.eclipse.jdt.internal.core.*;
020: import org.eclipse.jdt.internal.core.util.Util;
021:
022: public class PossibleMatch implements ICompilationUnit {
023:
024: public static final String NO_SOURCE_FILE_NAME = "NO SOURCE FILE NAME"; //$NON-NLS-1$
025:
026: public IResource resource;
027: public Openable openable;
028: public MatchingNodeSet nodeSet;
029: public char[][] compoundName;
030: CompilationUnitDeclaration parsedUnit;
031: public SearchDocument document;
032: private String sourceFileName;
033: private char[] source;
034:
035: public PossibleMatch(MatchLocator locator, IResource resource,
036: Openable openable, SearchDocument document,
037: boolean mustResolve) {
038: this .resource = resource;
039: this .openable = openable;
040: this .document = document;
041: this .nodeSet = new MatchingNodeSet(mustResolve);
042: char[] qualifiedName = getQualifiedName();
043: if (qualifiedName != null)
044: this .compoundName = CharOperation.splitOn('.',
045: qualifiedName);
046: }
047:
048: public void cleanUp() {
049: this .source = null;
050: if (this .parsedUnit != null) {
051: this .parsedUnit.cleanUp();
052: this .parsedUnit = null;
053: }
054: this .nodeSet = null;
055: }
056:
057: public boolean equals(Object obj) {
058: if (this .compoundName == null)
059: return super .equals(obj);
060: if (!(obj instanceof PossibleMatch))
061: return false;
062:
063: // By using the compoundName of the source file, multiple .class files (A, A$M...) are considered equal
064: // Even .class files for secondary types and their nested types
065: return CharOperation.equals(this .compoundName,
066: ((PossibleMatch) obj).compoundName);
067: }
068:
069: public char[] getContents() {
070: if (this .source != null)
071: return this .source;
072:
073: if (this .openable instanceof ClassFile) {
074: String fileName = getSourceFileName();
075: if (fileName == NO_SOURCE_FILE_NAME)
076: return CharOperation.NO_CHAR;
077:
078: SourceMapper sourceMapper = this .openable.getSourceMapper();
079: IType type = ((ClassFile) this .openable).getType();
080: return this .source = sourceMapper
081: .findSource(type, fileName);
082: }
083: return this .source = this .document.getCharContents();
084: }
085:
086: /**
087: * The exact openable file name. In particular, will be the originating .class file for binary openable with attached
088: * source.
089: * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
090: * @see PackageReferenceLocator#isDeclaringPackageFragment(IPackageFragment, org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
091: */
092: public char[] getFileName() {
093: return this .openable.getElementName().toCharArray();
094: }
095:
096: public char[] getMainTypeName() {
097: // The file is no longer opened to get its name => remove fix for bug 32182
098: return this .compoundName[this .compoundName.length - 1];
099: }
100:
101: public char[][] getPackageName() {
102: int length = this .compoundName.length;
103: if (length <= 1)
104: return CharOperation.NO_CHAR_CHAR;
105: return CharOperation.subarray(this .compoundName, 0, length - 1);
106: }
107:
108: /*
109: * Returns the fully qualified name of the main type of the compilation unit
110: * or the main type of the .java file that defined the class file.
111: */
112: private char[] getQualifiedName() {
113: if (this .openable instanceof CompilationUnit) {
114: // get file name
115: String fileName = this .openable.getElementName(); // working copy on a .class file may not have a resource, so use the element name
116: // get main type name
117: char[] mainTypeName = Util.getNameWithoutJavaLikeExtension(
118: fileName).toCharArray();
119: CompilationUnit cu = (CompilationUnit) this .openable;
120: return cu.getType(new String(mainTypeName))
121: .getFullyQualifiedName().toCharArray();
122: } else if (this .openable instanceof ClassFile) {
123: String fileName = getSourceFileName();
124: if (fileName == NO_SOURCE_FILE_NAME)
125: return ((ClassFile) this .openable).getType()
126: .getFullyQualifiedName('.').toCharArray();
127:
128: // Class file may have a source file name with ".java" extension (see bug 73784)
129: int index = Util.indexOfJavaLikeExtension(fileName);
130: String simpleName = index == -1 ? fileName : fileName
131: .substring(0, index);
132: PackageFragment pkg = (PackageFragment) this .openable
133: .getParent();
134: return Util.concatWith(pkg.names, simpleName, '.')
135: .toCharArray();
136: }
137: return null;
138: }
139:
140: /*
141: * Returns the source file name of the class file.
142: * Returns NO_SOURCE_FILE_NAME if not found.
143: */
144: private String getSourceFileName() {
145: if (this .sourceFileName != null)
146: return this .sourceFileName;
147:
148: this .sourceFileName = NO_SOURCE_FILE_NAME;
149: if (this .openable.getSourceMapper() != null) {
150: BinaryType type = (BinaryType) ((ClassFile) this .openable)
151: .getType();
152: ClassFileReader reader = MatchLocator.classFileReader(type);
153: if (reader != null) {
154: String fileName = type.sourceFileName(reader);
155: this .sourceFileName = fileName == null ? NO_SOURCE_FILE_NAME
156: : fileName;
157: }
158: }
159: return this .sourceFileName;
160: }
161:
162: public int hashCode() {
163: if (this .compoundName == null)
164: return super .hashCode();
165:
166: int hashCode = 0;
167: for (int i = 0, length = this .compoundName.length; i < length; i++)
168: hashCode += CharOperation.hashCode(this .compoundName[i]);
169: return hashCode;
170: }
171:
172: public String toString() {
173: return this .openable == null ? "Fake PossibleMatch" : this .openable.toString(); //$NON-NLS-1$
174: }
175: }
|