// below to the AjState for a compilation and recover it if switching
// between projects.
protected IHierarchy hierarchy;
-
- /* Map from String > String - it maps absolute paths for
- * inpath dirs/jars to workspace relative paths suitable for handle inclusion */
+
+ /*
+ * Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle
+ * inclusion
+ */
protected Map inpathMap;
private IRelationshipMap mapper;
private IElementHandleProvider handleProvider;
}
- private String getTypeNameFromHandle(String handle,Map cache) {
- String typename = (String)cache.get(handle);
- if (typename!=null) {
+ private String getTypeNameFromHandle(String handle, Map cache) {
+ String typename = (String) cache.get(handle);
+ if (typename != null) {
return typename;
}
// inpath handle - but for which type?
// let's do it the slow way, we can optimize this with a cache perhaps
int hasPackage = handle.indexOf('<');
- int typeLocation = handle.indexOf('[');
- if (typeLocation==-1) {
+ int typeLocation = handle.indexOf('[');
+ if (typeLocation == -1) {
typeLocation = handle.indexOf('}');
}
if (typeLocation == -1) {
return "";
}
StringBuffer qualifiedTypeNameFromHandle = new StringBuffer();
- if (hasPackage!=-1) {
- qualifiedTypeNameFromHandle.append(handle.substring(hasPackage+1,handle.indexOf('(',hasPackage)));
+ if (hasPackage != -1) {
+ qualifiedTypeNameFromHandle.append(handle.substring(hasPackage + 1, handle.indexOf('(', hasPackage)));
qualifiedTypeNameFromHandle.append('.');
}
- qualifiedTypeNameFromHandle.append(handle.substring(typeLocation+1));
+ qualifiedTypeNameFromHandle.append(handle.substring(typeLocation + 1));
typename = qualifiedTypeNameFromHandle.toString();
- cache.put(handle,typename);
+ cache.put(handle, typename);
return typename;
}
+
/**
* two kinds of relationships
*
if (isPhantomHandle(hid)) {
// inpath handle - but for which type?
// TODO promote cache for reuse during one whole model update
- if (!getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) {
+ if (!getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
continue;
}
}
// they need removing
for (Iterator targetsIter = targets.iterator(); targetsIter.hasNext();) {
String targethid = (String) targetsIter.next();
- if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) {
+ if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
continue;
}
// Does this point to the same type?
}
return (type.equals(containingType));
}
-
+
/**
* @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode
* @return true if the handle contains ';' - the char indicating that it is a phantom handle
*/
private boolean isPhantomHandle(String handle) {
- return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter())!=-1;
+ return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter()) != -1;
}
/**
}
public String getHandleElementForInpath(String binaryPath) {
- return (String)inpathMap.get(new File(binaryPath));
+ return (String) inpathMap.get(new File(binaryPath));
}
+ private List pieces = new ArrayList();
+
+ private Object intern(String substring) {
+ int lastIdx = -1;
+ if ((lastIdx = substring.lastIndexOf('/')) != -1) {
+ String pkg = substring.substring(0, lastIdx);
+ String type = substring.substring(lastIdx + 1);
+ pkg = internOneThing(pkg);
+ type = internOneThing(type);
+ return new String[] { pkg, type };
+ } else {
+ return internOneThing(substring);
+ }
+ }
+
+ private String internOneThing(String substring) {
+ // simple name
+ for (int p = 0, max = pieces.size(); p < max; p++) {
+ String s = (String) pieces.get(p);
+ if (s.equals(substring)) {
+ return s;
+ }
+ }
+ pieces.add(substring);
+ return substring;
+ }
+
+ /**
+ * What we can rely on: <br>
+ * - it is a method signature of the form (La/B;Lc/D;)LFoo;<br>
+ * - there are no generics<br>
+ *
+ * What we must allow for: - may use primitive refs (single chars rather than L)
+ */
+/*
+ public List compress(String s) {
+ int openParen = 0;
+ int closeParen = s.indexOf(')');
+ int pos = 1;
+ List compressed = new ArrayList();
+ // do the parens
+ while (pos < closeParen) {
+ char ch = s.charAt(pos);
+ if (ch == 'L') {
+ int idx = s.indexOf(';', pos);
+ compressed.add(intern(s.substring(pos + 1, idx)));
+ pos = idx + 1;
+ } else if (ch == '[') {
+ int x = pos;
+ while (s.charAt(++pos) == '[')
+ ;
+ // now pos will point at something not an array
+ compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
+ char ch2 = s.charAt(pos);
+ if (ch2 == 'L') {
+ int idx = s.indexOf(';', pos);
+ compressed.add(intern(s.substring(pos + 1, idx)));
+ pos = idx + 1;
+ } else if (ch2 == 'T') {
+ int idx = s.indexOf(';');
+ compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
+ pos = idx + 1;
+ } else {
+ compressed.add(toCharacter(s.charAt(pos)));
+ pos++;
+ }
+ } else {
+ // it is a primitive ref (SVBCZJ)
+ compressed.add(toCharacter(ch));
+ pos++;
+ }
+ }
+ // do the return type
+ pos++;
+ char ch = s.charAt(pos);
+ if (ch == 'L') {
+ int idx = s.indexOf(';', pos);
+ compressed.add(intern(s.substring(pos, idx)));
+ } else if (ch == '[') {
+ int x = pos;
+ while (s.charAt(++pos) == '[')
+ ;
+ // now pos will point at something not an array
+ compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
+ char ch2 = s.charAt(pos);
+ if (ch2 == 'L') {
+ int idx = s.indexOf(';', pos);
+ compressed.add(intern(s.substring(pos + 1, idx)));
+ pos = idx + 1;
+ } else if (ch2 == 'T') {
+ int idx = s.indexOf(';');
+ compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
+ pos = idx + 2;
+ } else {
+ compressed.add(toCharacter(s.charAt(pos)));
+ pos++;
+ }
+ } else {
+ // it is a primitive ref (SVBCZJ)
+ compressed.add(new Character(ch));
+ }
+ return compressed;
+
+ // char delimiter = '/';
+ // int pos = -1;
+ // List compressed = new ArrayList();
+ // int start = 0;
+ // while ((pos = s.indexOf(delimiter, start)) != -1) {
+ // String part = s.substring(start, pos);
+ // int alreadyRecorded = pieces.indexOf(part);
+ // if (alreadyRecorded != -1) {
+ // compressed.add(new Integer(alreadyRecorded));
+ // } else {
+ // compressed.add(new Integer(pieces.size()));
+ // pieces.add(part);
+ // }
+ // start = pos + 1;
+ // }
+ // // last piece
+ // String part = s.substring(start, s.length());
+ // int alreadyRecorded = pieces.indexOf(part);
+ // if (alreadyRecorded != -1) {
+ // compressed.add(youkirtyounew Integer(alreadyRecorded));
+ // } else {
+ // compressed.add(new Integer(pieces.size()));
+ // pieces.add(part);
+ // }
+ // return compressed;
+ }
+
+ static final Character charB = new Character('B');
+ static final Character charS = new Character('S');
+ static final Character charI = new Character('I');
+ static final Character charF = new Character('F');
+ static final Character charD = new Character('D');
+ static final Character charJ = new Character('J');
+ static final Character charC = new Character('C');
+ static final Character charV = new Character('V');
+ static final Character charZ = new Character('Z');
+
+ private Character toCharacter(char ch) {
+ switch (ch) {
+ case 'B':
+ return charB;
+ case 'S':
+ return charS;
+ case 'I':
+ return charI;
+ case 'F':
+ return charF;
+ case 'D':
+ return charD;
+ case 'J':
+ return charJ;
+ case 'C':
+ return charC;
+ case 'V':
+ return charV;
+ case 'Z':
+ return charZ;
+ default:
+ throw new IllegalStateException(new Character(ch).toString());
+ }
+ }
+
+ public String decompress(List refs, char delimiter) {
+ StringBuilder result = new StringBuilder();
+ result.append("(");
+ for (int i = 0, max = refs.size() - 1; i < max; i++) {
+ result.append(unintern(refs.get(i)));
+ }
+ result.append(")");
+ result.append(unintern(refs.get(refs.size() - 1)));
+ return result.toString();
+ }
+
+ private String unintern(Object o) {
+ if (o instanceof Character) {
+ return ((Character) o).toString();
+ } else if (o instanceof String[]) {
+ String[] strings = (String[]) o;
+ StringBuilder sb = new StringBuilder();
+ sb.append('L');
+ sb.append(strings[0]).append('/').append(strings[1]);
+ sb.append(';');
+ return sb.toString();
+ } else { // String
+ String so = (String) o;
+ if (so.endsWith(";")) {
+ // will be TT;
+ return so;
+ } else {
+ StringBuilder sb = new StringBuilder();
+ sb.append('L');
+ sb.append(so);
+ sb.append(';');
+ return sb.toString();
+ }
+ }
+ }
+ */
}
private final AsmManager asm;
- // Need to keep our own count of the number of initializers
- // because this information cannot be gained from the ipe.
- private int initializerCounter = 0;
-
private static final char[] empty = new char[] {};
private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() };
}
public String createHandleIdentifier(IProgramElement ipe) {
-
// AjBuildManager.setupModel --> top of the tree is either
// <root> or the .lst file
if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals("<root>"))) {
return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
}
} else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
- return String.valueOf(++initializerCounter).toCharArray();
+ // return String.valueOf(++initializerCounter).toCharArray();
+ // Look at any peer advice
+ int count = 1;
+ List kids = ipe.getParent().getChildren();
+ String ipeSig = ipe.getBytecodeSignature();
+ // remove return type from the signature - it should not be included in the comparison
+ int idx = 0;
+ if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) {
+ ipeSig = ipeSig.substring(0, idx);
+ }
+ if (ipeSig != null) {
+ if (ipeSig.indexOf("Lorg/aspectj/lang") != -1) {
+ if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
+ ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
+ }
+ if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
+ ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
+ }
+ if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
+ ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
+ }
+ }
+ }
+ for (Iterator iterator = kids.iterator(); iterator.hasNext();) {
+ IProgramElement object = (IProgramElement) iterator.next();
+ if (object.equals(ipe)) {
+ break;
+ }
+ if (object.getKind() == ipe.getKind()) {
+ if (object.getName().equals(ipe.getName())) {
+ String sig1 = object.getBytecodeSignature();
+ if (sig1 != null && (idx = sig1.indexOf(")")) != -1) {
+ sig1 = sig1.substring(0, idx);
+ }
+ // this code needs a speed overhaul... and some proper tests
+ // Two static parts because one may be enclosing jpsp (269522)
+ if (sig1 != null) {
+ if (sig1.indexOf("Lorg/aspectj/lang") != -1) {
+ if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
+ sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
+ }
+ if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
+ sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
+ }
+ if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
+ sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
+ }
+ }
+ }
+
+ if (sig1 == null && ipeSig == null || (sig1 != null && sig1.equals(ipeSig))) {
+ String existingHandle = object.getHandleIdentifier();
+ int suffixPosition = existingHandle.indexOf('!');
+ if (suffixPosition != -1) {
+ count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
+ } else {
+ if (count == 1) {
+ count = 2;
+ }
+ }
+ }
+ }
+ }
+ }
+ // if (count > 1) {
+ return new Integer(count).toString().toCharArray();
+ // return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
+ // }
} else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
int index = CharOperation.lastIndexOf('!', byteCodeName);
if (index != -1) {
}
public void initialize() {
- // reset the initializer count. This ensures we return the
- // same handle as JDT for initializers.
- initializerCounter = 0;
+ // nop
}
}
return s;
}
- public String getBytecodeSignature() {
- String s = (String) kvpairs.get("bytecodeSignature");
- // if (s==null) return UNDEFINED;
- return s;
- }
-
public void setBytecodeName(String s) {
if (kvpairs == Collections.EMPTY_MAP)
kvpairs = new HashMap();
}
public void setBytecodeSignature(String s) {
- if (kvpairs == Collections.EMPTY_MAP)
- kvpairs = new HashMap();
+ initMap();
+ // Different kinds of format here. The one worth compressing starts with a '(':
+ // (La/b/c/D;Le/f/g/G;)Ljava/lang/String;
+ // maybe want to avoid generics initially.
+ // boolean worthCompressing = s.charAt(0) == '(' && s.indexOf('<') == -1 && s.indexOf('P') == -1; // starts parentheses and
+ // no
+ // // generics
+ // if (worthCompressing) {
+ // kvpairs.put("bytecodeSignatureCompressed", asm.compress(s));
+ // } else {
kvpairs.put("bytecodeSignature", s);
+ // }
+ }
+
+ public String getBytecodeSignature() {
+ String s = (String) kvpairs.get("bytecodeSignature");
+ // if (s == null) {
+ // List compressed = (List) kvpairs.get("bytecodeSignatureCompressed");
+ // if (compressed != null) {
+ // return asm.decompress(compressed, '/');
+ // }
+ // }
+ // if (s==null) return UNDEFINED;
+ return s;
+ }
+
+ private void initMap() {
+ if (kvpairs == Collections.EMPTY_MAP) {
+ kvpairs = new HashMap();
+ }
}
public String getSourceSignature() {
}
public String getHandleIdentifier(boolean create) {
+ String h = handle;
if (null == handle && create) {
if (asm == null && name.equals("<build to view structure>")) {
- handle = "<build to view structure>";
+ h = "<build to view structure>";
} else {
try {
- handle = asm.getHandleProvider().createHandleIdentifier(this);
+ h = asm.getHandleProvider().createHandleIdentifier(this);
} catch (ArrayIndexOutOfBoundsException aioobe) {
throw new RuntimeException("AIOOBE whilst building handle for " + this, aioobe);
}
}
}
- return handle;
+ setHandleIdentifier(h);
+ return h;
}
public void setHandleIdentifier(String handle) {