Selaa lähdekoodia

copes with source folders in the model when searching for types

tags/V1_6_2
aclement 15 vuotta sitten
vanhempi
commit
17a082b29e
1 muutettua tiedostoa jossa 292 lisäystä ja 214 poistoa
  1. 292
    214
      asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java

+ 292
- 214
asm/src/org/aspectj/asm/internal/AspectJElementHierarchy.java Näytä tiedosto

@@ -11,149 +11,234 @@
* Andy Clement Extensions for better IDE representation
* ******************************************************************/


package org.aspectj.asm.internal;

import java.io.*;
import java.util.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aspectj.asm.*;
import org.aspectj.bridge.*;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IHierarchy;
import org.aspectj.asm.IProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;

/**
* @author Mik Kersten
*/
public class AspectJElementHierarchy implements IHierarchy {
private static final long serialVersionUID = 6462734311117048620L;
protected IProgramElement root = null;
protected String configFile = null;
private Map fileMap = null;
private Map handleMap = null;
private Map typeMap = null;
protected IProgramElement root = null;
protected String configFile = null;
private Map fileMap = null;
private Map handleMap = null;
private Map typeMap = null;
public IProgramElement getElement(String handle) {
return findElementForHandleOrCreate(handle, false);
}

public IProgramElement getRoot() {
return root;
}
public IProgramElement getRoot() {
return root;
}

public void setRoot(IProgramElement root) {
this.root = root;
handleMap = new HashMap();
typeMap = new HashMap();
}
public void setRoot(IProgramElement root) {
this.root = root;
handleMap = new HashMap();
typeMap = new HashMap();
}

public void addToFileMap( Object key, Object value ){
fileMap.put( key, value );
public void addToFileMap(Object key, Object value) {
fileMap.put(key, value);
}
public boolean removeFromFileMap(Object key) {
if (fileMap.containsKey(key)) {
return (fileMap.remove(key)!=null);
return (fileMap.remove(key) != null);
}
return true;
return true;
}

public void setFileMap(HashMap fileMap) {
this.fileMap = fileMap;
}
this.fileMap = fileMap;
}

public Object findInFileMap( Object key ) {
public Object findInFileMap(Object key) {
return fileMap.get(key);
}


public Set getFileMapEntrySet() {
return fileMap.entrySet();
}
public boolean isValid() {
return root != null && fileMap != null;
}
/**
return root != null && fileMap != null;
}
/**
* Returns the first match
*
* @param parent
* @param kind not null
* @param kind not null
* @return null if not found
*/
public IProgramElement findElementForSignature(IProgramElement parent, IProgramElement.Kind kind, String signature) {
for (Iterator it = parent.getChildren().iterator(); it.hasNext(); ) {
IProgramElement node = (IProgramElement)it.next();
for (Iterator it = parent.getChildren().iterator(); it.hasNext();) {
IProgramElement node = (IProgramElement) it.next();
if (node.getKind() == kind && signature.equals(node.toSignatureString())) {
return node;
} else {
IProgramElement childSearch = findElementForSignature(node, kind, signature);
if (childSearch != null) return childSearch;
if (childSearch != null)
return childSearch;
}
}
return null;
}
public IProgramElement findElementForLabel(
IProgramElement parent,
IProgramElement.Kind kind,
String label) {
for (Iterator it = parent.getChildren().iterator(); it.hasNext(); ) {
IProgramElement node = (IProgramElement)it.next();

public IProgramElement findElementForLabel(IProgramElement parent, IProgramElement.Kind kind, String label) {

for (Iterator it = parent.getChildren().iterator(); it.hasNext();) {
IProgramElement node = (IProgramElement) it.next();
if (node.getKind() == kind && label.equals(node.toLabelString())) {
return node;
} else {
IProgramElement childSearch = findElementForLabel(node, kind, label);
if (childSearch != null) return childSearch;
if (childSearch != null)
return childSearch;
}
}
return null;
return null;
}
/**
* @param packageName if null default package is searched
* @param className can't be null
*/
* Find the entry in the model that represents a particular type.
*
* @param packageName the package in which the type is declared or null for the default package
* @param typeName the name of the type
* @return the IProgramElement representing the type, or null if not found
*/
public IProgramElement findElementForType(String packageName, String typeName) {
StringBuffer keyb = (packageName == null) ? new StringBuffer() :
new StringBuffer(packageName);
keyb.append(".");
keyb.append(typeName);
// Build a cache key and check the cache
StringBuffer keyb = (packageName == null) ? new StringBuffer() : new StringBuffer(packageName);
keyb.append(".").append(typeName);
String key = keyb.toString();
IProgramElement ret = (IProgramElement) typeMap.get(key);
if (ret == null) {
IProgramElement packageNode = null;
if (packageName == null) {
packageNode = root;
} else {
if (root == null) return null;
List kids = root.getChildren();
if (kids == null) return null;
for (Iterator it = kids.iterator(); it.hasNext(); ) {
IProgramElement node = (IProgramElement)it.next();
if (packageName.equals(node.getName())) {
packageNode = node;
}
}
if (packageNode == null) return null;
}
IProgramElement cachedValue = (IProgramElement) typeMap.get(key);
if (cachedValue != null) {
return cachedValue;
}

List packageNodes = findMatchingPackages(packageName);

for (Iterator iterator = packageNodes.iterator(); iterator.hasNext();) {
IProgramElement pkg = (IProgramElement) iterator.next();
// this searches each file for a class
for (Iterator it = packageNode.getChildren().iterator(); it.hasNext(); ) {
IProgramElement fileNode = (IProgramElement)it.next();
for (Iterator it = pkg.getChildren().iterator(); it.hasNext();) {
IProgramElement fileNode = (IProgramElement) it.next();
IProgramElement cNode = findClassInNodes(fileNode.getChildren(), typeName, typeName);
if (cNode != null) {
ret = cNode;
typeMap.put(key,ret);
}
}
typeMap.put(key, cNode);
return cNode;
}
}
}
return ret;
return null;

// IProgramElement packageNode = null;
// if (packageName == null) {
// packageNode = root;
// } else {
// if (root == null)
// return null;
// List kids = root.getChildren();
// if (kids == null) {
// return null;
// }
// for (Iterator it = kids.iterator(); it.hasNext() && packageNode == null;) {
// IProgramElement node = (IProgramElement) it.next();
// if (packageName.equals(node.getName())) {
// packageNode = node;
// }
// }
// if (packageNode == null) {
// return null;
// }
// }

// // this searches each file for a class
// for (Iterator it = packageNode.getChildren().iterator(); it.hasNext();) {
// IProgramElement fileNode = (IProgramElement) it.next();
// IProgramElement cNode = findClassInNodes(fileNode.getChildren(), typeName, typeName);
// if (cNode != null) {
// typeMap.put(key, cNode);
// return cNode;
// }
// }
// return null;
}

/**
* Look for any package nodes matching the specified package name. There may be multiple in the case where the types within a
* package are split across source folders.
*
* @param packagename the packagename being searched for
* @return a list of package nodes that match that name
*/
public List/* IProgramElement */findMatchingPackages(String packagename) {
List children = root.getChildren();
// The children might be source folders or packages
if (children.size() == 0) {
return Collections.EMPTY_LIST;
}
if (((IProgramElement) children.get(0)).getKind() == IProgramElement.Kind.SOURCE_FOLDER) {
// dealing with source folders
List matchingPackageNodes = new ArrayList();
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
IProgramElement sourceFolder = (IProgramElement) iterator.next();
List possiblePackageNodes = sourceFolder.getChildren();
for (Iterator iterator2 = possiblePackageNodes.iterator(); iterator2.hasNext();) {
IProgramElement possiblePackageNode = (IProgramElement) iterator2.next();
if (possiblePackageNode.getKind() == IProgramElement.Kind.PACKAGE) {
if (possiblePackageNode.getName().equals(packagename)) {
matchingPackageNodes.add(possiblePackageNode);
}
}
}
}
return matchingPackageNodes;
} else {
// dealing directly with packages below the root, no source folders. Therefore at most one
// thing to return in the list
if (packagename == null) {
// default package
List result = new ArrayList();
result.add(root);
return result;
}
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
IProgramElement possiblePackage = (IProgramElement) iterator.next();
if (possiblePackage.getKind() == IProgramElement.Kind.PACKAGE) {
if (possiblePackage.getName().equals(packagename)) {
List result = new ArrayList();
result.add(possiblePackage);
return result;
}
}
}
}
return Collections.EMPTY_LIST;
}

private IProgramElement findClassInNodes(Collection nodes, String name, String typeName) {
String baseName;
String innerName;
@@ -163,20 +248,22 @@ public class AspectJElementHierarchy implements IHierarchy {
innerName = null;
} else {
baseName = name.substring(0, dollar);
innerName = name.substring(dollar+1);
innerName = name.substring(dollar + 1);
}
for (Iterator j = nodes.iterator(); j.hasNext(); ) {
IProgramElement classNode = (IProgramElement)j.next();
for (Iterator j = nodes.iterator(); j.hasNext();) {
IProgramElement classNode = (IProgramElement) j.next();
if (baseName.equals(classNode.getName())) {
if (innerName == null) return classNode;
else return findClassInNodes(classNode.getChildren(), innerName, typeName);
if (innerName == null)
return classNode;
else
return findClassInNodes(classNode.getChildren(), innerName, typeName);
} else if (name.equals(classNode.getName())) {
return classNode;
} else if (typeName.equals(classNode.getBytecodeSignature())) {
} else if (typeName.equals(classNode.getBytecodeSignature())) {
return classNode;
} else if (classNode.getChildren() != null && !classNode.getChildren().isEmpty()){
IProgramElement node = findClassInNodes(classNode.getChildren(),name, typeName);
} else if (classNode.getChildren() != null && !classNode.getChildren().isEmpty()) {
IProgramElement node = findClassInNodes(classNode.getChildren(), name, typeName);
if (node != null) {
return node;
}
@@ -185,69 +272,63 @@ public class AspectJElementHierarchy implements IHierarchy {
return null;
}


/**
* @param sourceFilePath modified to '/' delimited path for consistency
* @return a new structure node for the file if it was not found in the model
* @param sourceFilePath modified to '/' delimited path for consistency
* @return a new structure node for the file if it was not found in the model
*/
public IProgramElement findElementForSourceFile(String sourceFile) {
try {
if (!isValid() || sourceFile == null) {
return IHierarchy.NO_STRUCTURE;
} else {
String correctedPath =
AsmManager.getDefault().getCanonicalFilePath(new File(sourceFile));
//StructureNode node = (StructureNode)getFileMap().get(correctedPath);//findFileNode(filePath, model);
IProgramElement node = (IProgramElement)findInFileMap(correctedPath);//findFileNode(filePath, model);
if (node != null) {
return node;
} else {
return createFileStructureNode(correctedPath);
}
}
try {
if (!isValid() || sourceFile == null) {
return IHierarchy.NO_STRUCTURE;
} else {
String correctedPath = AsmManager.getDefault().getCanonicalFilePath(new File(sourceFile));
// StructureNode node = (StructureNode)getFileMap().get(correctedPath);//findFileNode(filePath, model);
IProgramElement node = (IProgramElement) findInFileMap(correctedPath);// findFileNode(filePath, model);
if (node != null) {
return node;
} else {
return createFileStructureNode(correctedPath);
}
}
} catch (Exception e) {
return IHierarchy.NO_STRUCTURE;
}
}
}

/**
* TODO: discriminate columns
*/
public IProgramElement findElementForSourceLine(ISourceLocation location) {
try {
return findElementForSourceLine(
AsmManager.getDefault().getCanonicalFilePath(
location.getSourceFile()),
location.getLine());
return findElementForSourceLine(AsmManager.getDefault().getCanonicalFilePath(location.getSourceFile()), location
.getLine());
} catch (Exception e) {
return null;
}
}

/**
* Never returns null
* Never returns null
*
* @param sourceFilePath canonicalized path for consistency
* @param lineNumber if 0 or 1 the corresponding file node will be returned
* @return a new structure node for the file if it was not found in the model
* @param sourceFilePath canonicalized path for consistency
* @param lineNumber if 0 or 1 the corresponding file node will be returned
* @return a new structure node for the file if it was not found in the model
*/
public IProgramElement findElementForSourceLine(String sourceFilePath, int lineNumber) {
String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(
new File(sourceFilePath));
String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(new File(sourceFilePath));
IProgramElement node = findNodeForSourceLineHelper(root, canonicalSFP, lineNumber, -1);
if (node != null) {
return node;
} else {
return node;
} else {
return createFileStructureNode(sourceFilePath);
}
}

public IProgramElement findElementForOffSet(String sourceFilePath, int lineNumber, int offSet) {
String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(
new File(sourceFilePath));
String canonicalSFP = AsmManager.getDefault().getCanonicalFilePath(new File(sourceFilePath));
IProgramElement node = findNodeForSourceLineHelper(root, canonicalSFP, lineNumber, offSet);
if (node != null) {
return node;
return node;
} else {
return createFileStructureNode(sourceFilePath);
}
@@ -259,68 +340,61 @@ public class AspectJElementHierarchy implements IHierarchy {
if (lastSlash == -1) {
lastSlash = sourceFilePath.lastIndexOf('/');
}
// '!' is used like in URLs "c:/blahblah/X.jar!a/b.class"
// '!' is used like in URLs "c:/blahblah/X.jar!a/b.class"
int i = sourceFilePath.lastIndexOf('!');
int j = sourceFilePath.indexOf(".class");
if (i > lastSlash && i != -1 && j != -1) {
// we are a binary aspect in the default package
lastSlash = i;
}
String fileName = sourceFilePath.substring(lastSlash+1);
IProgramElement fileNode = new ProgramElement(fileName, IProgramElement.Kind.FILE_JAVA, new SourceLocation(new File(sourceFilePath), 1, 1),0,null,null);
//fileNode.setSourceLocation();
String fileName = sourceFilePath.substring(lastSlash + 1);
IProgramElement fileNode = new ProgramElement(fileName, IProgramElement.Kind.FILE_JAVA, new SourceLocation(new File(
sourceFilePath), 1, 1), 0, null, null);
// fileNode.setSourceLocation();
fileNode.addChild(NO_STRUCTURE);
return fileNode;
}


private IProgramElement findNodeForSourceLineHelper(IProgramElement node, String sourceFilePath, int lineNumber, int offSet) {
if (matches(node, sourceFilePath, lineNumber, offSet)
&& !hasMoreSpecificChild(node, sourceFilePath, lineNumber, offSet)) {
return node;
}
if (matches(node, sourceFilePath, lineNumber, offSet) && !hasMoreSpecificChild(node, sourceFilePath, lineNumber, offSet)) {
return node;
}

if (node != null && node.getChildren() != null) {
for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
IProgramElement foundNode = findNodeForSourceLineHelper(
(IProgramElement)it.next(),
sourceFilePath,
lineNumber,
offSet);
if (foundNode != null) return foundNode;
for (Iterator it = node.getChildren().iterator(); it.hasNext();) {
IProgramElement foundNode = findNodeForSourceLineHelper((IProgramElement) it.next(), sourceFilePath, lineNumber,
offSet);
if (foundNode != null)
return foundNode;
}
}
return null;
return null;
}
private boolean matches(IProgramElement node, String sourceFilePath, int lineNumber, int offSet) {
// try {
// if (node != null && node.getSourceLocation() != null)
// System.err.println("====\n1: " +
// sourceFilePath + "\n2: " +
// node.getSourceLocation().getSourceFile().getCanonicalPath().equals(sourceFilePath)
// );
return node != null
// try {
// if (node != null && node.getSourceLocation() != null)
// System.err.println("====\n1: " +
// sourceFilePath + "\n2: " +
// node.getSourceLocation().getSourceFile().getCanonicalPath().equals(sourceFilePath)
// );
return node != null
&& node.getSourceLocation() != null
&& node.getSourceLocation().getSourceFile().getAbsolutePath().equals(sourceFilePath)
&& ((offSet != -1 && node.getSourceLocation().getOffset() == offSet)
|| offSet == -1 )
&& ((node.getSourceLocation().getLine() <= lineNumber
&& node.getSourceLocation().getEndLine() >= lineNumber)
||
(lineNumber <= 1
&& node.getKind().isSourceFile())
);
// } catch (IOException ioe) {
// return false;
// }
}
&& ((offSet != -1 && node.getSourceLocation().getOffset() == offSet) || offSet == -1)
&& ((node.getSourceLocation().getLine() <= lineNumber && node.getSourceLocation().getEndLine() >= lineNumber) || (lineNumber <= 1 && node
.getKind().isSourceFile()));
// } catch (IOException ioe) {
// return false;
// }
}

private boolean hasMoreSpecificChild(IProgramElement node, String sourceFilePath, int lineNumber, int offSet) {
for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
IProgramElement child = (IProgramElement)it.next();
if (matches(child, sourceFilePath, lineNumber, offSet)) return true;
for (Iterator it = node.getChildren().iterator(); it.hasNext();) {
IProgramElement child = (IProgramElement) it.next();
if (matches(child, sourceFilePath, lineNumber, offSet))
return true;
}
return false;
}
@@ -332,11 +406,11 @@ public class AspectJElementHierarchy implements IHierarchy {
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
public IProgramElement findElementForHandle(String handle) {
return findElementForHandleOrCreate(handle,true);
return findElementForHandleOrCreate(handle, true);
}
// TODO: optimize this lookup
// only want to create a file node if can't find the IPE if called through
// findElementForHandle() to mirror behaviour before pr141730
@@ -346,81 +420,84 @@ public class AspectJElementHierarchy implements IHierarchy {
if (ipe != null) {
return ipe;
}
ipe = findElementForHandle(root,handle);
ipe = findElementForHandle(root, handle);
if (ipe == null && create) {
ipe = createFileStructureNode(getFilename(handle));
}
if (ipe != null) {
cache(handle,ipe);
cache(handle, ipe);
}
return ipe;
}
private IProgramElement findElementForHandle(IProgramElement parent, String handle) {
for (Iterator it = parent.getChildren().iterator(); it.hasNext(); ) {
IProgramElement node = (IProgramElement)it.next();
for (Iterator it = parent.getChildren().iterator(); it.hasNext();) {
IProgramElement node = (IProgramElement) it.next();
String nodeHid = node.getHandleIdentifier();
if (handle.equals(nodeHid)) {
return node;
} else {
if (handle.startsWith(nodeHid)) {
// it must be down here if it is anywhere
IProgramElement childSearch = findElementForHandle(node,handle);
if (childSearch != null) return childSearch;
IProgramElement childSearch = findElementForHandle(node, handle);
if (childSearch != null)
return childSearch;
}
}
}
return null;
}
//
// private IProgramElement findElementForBytecodeInfo(
// IProgramElement node,
// String parentName,
// String name,
// String signature) {
// for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
// IProgramElement curr = (IProgramElement)it.next();
// if (parentName.equals(curr.getParent().getBytecodeName())
// && name.equals(curr.getBytecodeName())
// && signature.equals(curr.getBytecodeSignature())) {
// return node;
// } else {
// IProgramElement childSearch = findElementForBytecodeInfo(curr, parentName, name, signature);
// if (childSearch != null) return childSearch;
// }
// }
// return null;
// }
//
// private IProgramElement findElementForBytecodeInfo(
// IProgramElement node,
// String parentName,
// String name,
// String signature) {
// for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
// IProgramElement curr = (IProgramElement)it.next();
// if (parentName.equals(curr.getParent().getBytecodeName())
// && name.equals(curr.getBytecodeName())
// && signature.equals(curr.getBytecodeSignature())) {
// return node;
// } else {
// IProgramElement childSearch = findElementForBytecodeInfo(curr, parentName, name, signature);
// if (childSearch != null) return childSearch;
// }
// }
// return null;
// }
protected void cache(String handle, IProgramElement pe) {
if (!AsmManager.isCompletingTypeBindings()) {
handleMap.put(handle,pe);
handleMap.put(handle, pe);
}
}

public void flushTypeMap() {
typeMap.clear();
}

public void flushHandleMap() {
handleMap.clear();
}

public void flushFileMap() {
fileMap.clear();
}

// TODO rename this method ... it does more than just the handle map
// TODO rename this method ... it does more than just the handle map
public void updateHandleMap(Set deletedFiles) {
// Only delete the entries we need to from the handle map - for performance reasons
List forRemoval = new ArrayList();
Set k = handleMap.keySet();
for (Iterator iter = k.iterator(); iter.hasNext();) {
String handle = (String) iter.next();
IProgramElement ipe = (IProgramElement)handleMap.get(handle);
if (deletedFiles.contains(getCanonicalFilePath(ipe)))forRemoval.add(handle);
IProgramElement ipe = (IProgramElement) handleMap.get(handle);
if (deletedFiles.contains(getCanonicalFilePath(ipe)))
forRemoval.add(handle);
}
for (Iterator iter = forRemoval.iterator(); iter.hasNext();) {
String handle = (String) iter.next();
@@ -430,8 +507,9 @@ public class AspectJElementHierarchy implements IHierarchy {
k = typeMap.keySet();
for (Iterator iter = k.iterator(); iter.hasNext();) {
String typeName = (String) iter.next();
IProgramElement ipe = (IProgramElement)typeMap.get(typeName);
if (deletedFiles.contains(getCanonicalFilePath(ipe))) forRemoval.add(typeName);
IProgramElement ipe = (IProgramElement) typeMap.get(typeName);
if (deletedFiles.contains(getCanonicalFilePath(ipe)))
forRemoval.add(typeName);
}
for (Iterator iter = forRemoval.iterator(); iter.hasNext();) {
String typeName = (String) iter.next();
@@ -441,25 +519,25 @@ public class AspectJElementHierarchy implements IHierarchy {
k = fileMap.keySet();
for (Iterator iter = k.iterator(); iter.hasNext();) {
String filePath = (String) iter.next();
IProgramElement ipe = (IProgramElement)fileMap.get(filePath);
if (deletedFiles.contains(getCanonicalFilePath(ipe))) forRemoval.add(filePath);
IProgramElement ipe = (IProgramElement) fileMap.get(filePath);
if (deletedFiles.contains(getCanonicalFilePath(ipe)))
forRemoval.add(filePath);
}
for (Iterator iter = forRemoval.iterator(); iter.hasNext();) {
String filePath = (String) iter.next();
fileMap.remove(filePath);
}
}
private String getFilename(String hid) {
return AsmManager.getDefault().getHandleProvider().getFileForHandle(hid);
}
private String getCanonicalFilePath(IProgramElement ipe) {
if (ipe.getSourceLocation() != null) {
return AsmManager.getDefault().getCanonicalFilePath(ipe.getSourceLocation().getSourceFile());
return AsmManager.getDefault().getCanonicalFilePath(ipe.getSourceLocation().getSourceFile());
}
return "";
}

}


Loading…
Peruuta
Tallenna