123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- /********************************************************************
- * Copyright (c) 2006 Contributors. All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors: IBM Corporation - initial API and implementation
- * Helen Hawkins - initial version
- *******************************************************************/
- package org.aspectj.asm.internal;
-
- import java.io.File;
- import java.util.List;
-
- import org.aspectj.asm.AsmManager;
- import org.aspectj.asm.IElementHandleProvider;
- import org.aspectj.asm.IProgramElement;
- import org.aspectj.bridge.ISourceLocation;
-
- /**
- * Creates JDT-like handles, for example
- * <ul>
- * <li>method with string argument: {@code <tjp}<code>{</code>{@code Demo.java[Demo~main~\[QString;}</li>
- * <li>method with generic argument: {@code <pkg}<code>{</code>{@code MyClass.java[MyClass~myMethod~QList\<QString;>;}</li>
- * <li>aspect: {@code <pkg*A1.aj}<code>}</code>{@code A1}</li>
- * <li>advice with Integer arg: {@code <pkg*A8.aj}<code>}</code>{@code A8&afterReturning&QInteger;}</li>
- * <li>method call: {@code <pkg*A10.aj[C~m1?method-call(void pkg.C.m2())}</li>
- * </ul>
- */
- public class JDTLikeHandleProvider implements IElementHandleProvider {
-
- private final AsmManager asm;
-
- private static final char[] empty = new char[] {};
- private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() };
-
- private static final String backslash = "\\";
- private static final String emptyString = "";
-
- public JDTLikeHandleProvider(AsmManager asm) {
- this.asm = asm;
- }
-
- public void initialize() {
- // nothing to do
- }
-
- 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 "";
- } else if (ipe.getHandleIdentifier(false) != null) {
- // have already created the handle for this ipe
- // therefore just return it
- return ipe.getHandleIdentifier();
- } else if (ipe.getKind().equals(IProgramElement.Kind.FILE_LST)) {
- String configFile = asm.getHierarchy().getConfigFile();
- int start = configFile.lastIndexOf(File.separator);
- int end = configFile.lastIndexOf(".lst");
- if (end != -1) {
- configFile = configFile.substring(start + 1, end);
- } else {
- configFile = new StringBuilder("=").append(configFile.substring(start + 1)).toString();
- }
- ipe.setHandleIdentifier(configFile);
- return configFile;
- } else if (ipe.getKind() == IProgramElement.Kind.SOURCE_FOLDER) {
- StringBuilder sb = new StringBuilder();
- sb.append(createHandleIdentifier(ipe.getParent())).append("/");
- // pr249216 - escape any embedded slashes
- String folder = ipe.getName();
- if (folder.endsWith("/")) {
- folder = folder.substring(0, folder.length() - 1);
- }
- if (folder.contains("/")) {
- folder = folder.replace("/", "\\/");
- }
- sb.append(folder);
- String handle = sb.toString();
- ipe.setHandleIdentifier(handle);
- return handle;
- }
- IProgramElement parent = ipe.getParent();
- if (parent != null && parent.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) {
- // want to miss out '#import declaration' in the handle
- parent = ipe.getParent().getParent();
- }
-
- StringBuilder handle = new StringBuilder();
- // add the handle for the parent
- handle.append(createHandleIdentifier(parent));
- // add the correct delimiter for this ipe
- handle.append(HandleProviderDelimiter.getDelimiter(ipe));
- // add the name and any parameters unless we're an initializer
- // (initializer's names are '...')
- if (!ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
- if (ipe.getKind() == IProgramElement.Kind.CLASS && ipe.getName().endsWith("{..}")) {
- // format: 'new Runnable() {..}' but its anon-y-mouse
- // dont append anything, there may be a count to follow though (!<n>)
- } else {
- if (ipe.getKind() == IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR) {
- handle.append(ipe.getName()).append("_new").append(getParameters(ipe));
- } else {
- // if (ipe.getKind() == IProgramElement.Kind.PACKAGE && ipe.getName().equals("DEFAULT")) {
- // // the delimiter will be in there, but skip the word DEFAULT as it is just a placeholder
- // } else {
- if (ipe.getKind().isDeclareAnnotation()) {
- // escape the @ (pr249216c9)
- handle.append("declare \\@").append(ipe.getName().substring(9)).append(getParameters(ipe));
- } else {
- if (ipe.getFullyQualifiedName() != null) {
- handle.append(ipe.getFullyQualifiedName());
- } else {
- handle.append(ipe.getName());
- }
- handle.append(getParameters(ipe));
- }
- }
- // }
- }
- }
- // add the count, for example '!2' if its the second ipe of its
- // kind in the aspect
- handle.append(getCount(ipe));
-
- ipe.setHandleIdentifier(handle.toString());
- return handle.toString();
- }
-
- private String getParameters(IProgramElement ipe) {
- if (ipe.getParameterSignatures() == null || ipe.getParameterSignatures().isEmpty()) {
- return "";
- }
- List<String> sourceRefs = ipe.getParameterSignaturesSourceRefs();
- List<char[]> parameterTypes = ipe.getParameterSignatures();
- StringBuilder sb = new StringBuilder();
- if (sourceRefs != null) {
- for (String sourceRef : sourceRefs) {
- sb.append(HandleProviderDelimiter.getDelimiter(ipe));
- sb.append(sourceRef);
- }
- } else {
- for (char[] element : parameterTypes) {
- sb.append(HandleProviderDelimiter.getDelimiter(ipe));
- sb.append(NameConvertor.createShortName(element, false, false));
- }
- }
- return sb.toString();
- }
-
- /**
- * Determine a count to be suffixed to the handle, this is only necessary for identical looking entries at the same level in the
- * model (for example two anonymous class declarations). The format is !<n> where n will be greater than 2.
- *
- * @param ipe the program element for which the handle is being constructed
- * @return a char suffix that will either be empty or of the form "!<n>"
- */
- private char[] getCount(IProgramElement ipe) {
- // TODO could optimize this code
- char[] byteCodeName = ipe.getBytecodeName().toCharArray();
-
- if (ipe.getKind().isInterTypeMember()) {
- int count = 1;
- List<IProgramElement> kids = ipe.getParent().getChildren();
- for (IProgramElement object : kids) {
- if (object.equals(ipe)) {
- break;
- }
- if (object.getKind().isInterTypeMember()) {
- if (object.getName().equals(ipe.getName()) && getParameters(object).equals(getParameters(ipe))) {
- String existingHandle = object.getHandleIdentifier();
- int suffixPosition = existingHandle.indexOf('!');
- if (suffixPosition != -1) {
- count = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- if (count > 1) {
- return CharOperation.concat(countDelim, Integer.toString(count).toCharArray());
- }
- } else if (ipe.getKind().isDeclare()) {
- // // look at peer declares
- int count = computeCountBasedOnPeers(ipe);
- if (count > 1) {
- return CharOperation.concat(countDelim, Integer.toString(count).toCharArray());
- }
- } else if (ipe.getKind().equals(IProgramElement.Kind.ADVICE)) {
- // Look at any peer advice
- int count = 1;
- List<IProgramElement> 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;
- ipeSig = shortenIpeSig(ipeSig);
- for (IProgramElement object : kids) {
- 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.contains("Lorg/aspectj/lang")) {
- 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 = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- }
- if (count > 1) {
- return CharOperation.concat(countDelim, Integer.toString(count).toCharArray());
- }
- } else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
- // return String.valueOf(++initializerCounter).toCharArray();
- // Look at any peer advice
- int count = 1;
- List<IProgramElement> 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;
- ipeSig = shortenIpeSig(ipeSig);
- for (IProgramElement object : kids) {
- 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.contains("Lorg/aspectj/lang")) {
- 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 = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- }
- // if (count > 1) {
- return Integer.toString(count).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) {
- return convertCount(CharOperation.subarray(byteCodeName, index + 1, byteCodeName.length));
- }
- } else if (ipe.getKind() == IProgramElement.Kind.CLASS) {
- // depends on previous children
- int count = 1;
- List<IProgramElement> kids = ipe.getParent().getChildren();
- if (ipe.getName().endsWith("{..}")) {
- // only depends on previous anonymous children, name irrelevant
- for (IProgramElement object : kids) {
- if (object.equals(ipe)) {
- break;
- }
- if (object.getKind() == ipe.getKind()) {
- if (object.getName().endsWith("{..}")) {
- String existingHandle = object.getHandleIdentifier();
- int suffixPosition = existingHandle.lastIndexOf('!');
- int lastSquareBracket = existingHandle.lastIndexOf('['); // type delimiter
- if (suffixPosition != -1 && lastSquareBracket < suffixPosition) { // pr260384
- count = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- } else {
- for (IProgramElement object : kids) {
- if (object.equals(ipe)) {
- break;
- }
- if (object.getKind() == ipe.getKind()) {
- if (object.getName().equals(ipe.getName())) {
- String existingHandle = object.getHandleIdentifier();
- int suffixPosition = existingHandle.lastIndexOf('!');
- int lastSquareBracket = existingHandle.lastIndexOf('['); // type delimiter
- if (suffixPosition != -1 && lastSquareBracket < suffixPosition) { // pr260384
- count = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- }
- if (count > 1) {
- return CharOperation.concat(countDelim, Integer.toString(count).toCharArray());
- }
- }
- return empty;
- }
-
- private String shortenIpeSig(String ipeSig) {
- int idx;
- if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) {
- ipeSig = ipeSig.substring(0, idx);
- }
- if (ipeSig != null) {
- if (ipeSig.contains("Lorg/aspectj/lang")) {
- 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;"));
- }
- }
- }
- return ipeSig;
- }
-
- private int computeCountBasedOnPeers(IProgramElement ipe) {
- int count = 1;
- for (IProgramElement object : ipe.getParent().getChildren()) {
- if (object.equals(ipe)) {
- break;
- }
- if (object.getKind() == ipe.getKind()) {
- if (object.getKind().toString().equals(ipe.getKind().toString())) {
- String existingHandle = object.getHandleIdentifier();
- int suffixPosition = existingHandle.indexOf('!');
- if (suffixPosition != -1) {
- count = Integer.parseInt(existingHandle.substring(suffixPosition + 1)) + 1;
- } else {
- if (count == 1) {
- count = 2;
- }
- }
- }
- }
- }
- return count;
- }
-
- /**
- * Only returns the count if it's not equal to 1
- */
- private char[] convertCount(char[] c) {
- if ((c.length == 1 && c[0] != ' ' && c[0] != '1') || c.length > 1) {
- return CharOperation.concat(countDelim, c);
- }
- return empty;
- }
-
- public String getFileForHandle(String handle) {
- IProgramElement node = asm.getHierarchy().getElement(handle);
- if (node != null) {
- return asm.getCanonicalFilePath(node.getSourceLocation().getSourceFile());
- } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
- || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
- // it's something like *MyAspect.aj or {MyClass.java. In other words
- // it's a file node that's been created with no children and no
- // parent
- return backslash + handle.substring(1);
- }
- return emptyString;
- }
-
- public int getLineNumberForHandle(String handle) {
- IProgramElement node = asm.getHierarchy().getElement(handle);
- if (node != null) {
- return node.getSourceLocation().getLine();
- } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
- || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
- // it's something like *MyAspect.aj or {MyClass.java. In other words
- // it's a file node that's been created with no children and no
- // parent
- return 1;
- }
- return -1;
- }
-
- public int getOffSetForHandle(String handle) {
- IProgramElement node = asm.getHierarchy().getElement(handle);
- if (node != null) {
- return node.getSourceLocation().getOffset();
- } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
- || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
- // it's something like *MyAspect.aj or {MyClass.java. In other words
- // it's a file node that's been created with no children and no
- // parent
- return 0;
- }
- return -1;
- }
-
- public String createHandleIdentifier(ISourceLocation location) {
- IProgramElement node = asm.getHierarchy().findElementForSourceLine(location);
- if (node != null) {
- return createHandleIdentifier(node);
- }
- return null;
- }
-
- public String createHandleIdentifier(File sourceFile, int line, int column, int offset) {
- IProgramElement node = asm.getHierarchy().findElementForOffSet(sourceFile.getAbsolutePath(), line, offset);
- if (node != null) {
- return createHandleIdentifier(node);
- }
- return null;
- }
-
- public boolean dependsOnLocation() {
- // handles are independent of soureLocations therefore return false
- return false;
- }
-
- }
|