### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java,v retrieving revision 1.44 diff -u -r1.44 MethodInfo.java --- compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java 24 Nov 2006 01:32:07 -0000 1.44 +++ compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java 16 Feb 2007 17:37:49 -0000 @@ -12,12 +12,14 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; +import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.util.Util; public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Comparable { static private final char[][] noException = CharOperation.NO_CHAR_CHAR; + static private final char[][] noArgumentNames = CharOperation.NO_CHAR_CHAR; protected int accessFlags; protected int attributeBytes; protected char[] descriptor; @@ -26,6 +28,8 @@ protected char[] signature; protected int signatureUtf8Offset; protected long tagBits; + protected char[][] argumentNames; + protected int argumentNamesIndex; public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset) { MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); @@ -193,7 +197,10 @@ * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames() */ public char[][] getArgumentNames() { - return null; + if (this.argumentNames == null) { + readCodeAttribute(); + } + return this.argumentNames; } public Object getDefaultValue() { return null; @@ -283,6 +290,7 @@ getMethodDescriptor(); getExceptionTypeNames(); getGenericSignature(); + getArgumentNames(); reset(); } /** @@ -404,4 +412,73 @@ .append(desc) .append('}'); } +private void readCodeAttribute() { + int attributesCount = u2At(6); + int readOffset = 8; + if (attributesCount != 0) { + for (int i = 0; i < attributesCount; i++) { + int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; + char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + if (CharOperation.equals(attributeName, AttributeNamesConstants.CodeName)) { + decodeCodeAttribute(readOffset); + if (this.argumentNames == null) { + this.argumentNames = noArgumentNames; + } + return; + } else { + readOffset += (6 + u4At(readOffset + 2)); + } + } + } + this.argumentNames = noArgumentNames; +} +private void decodeCodeAttribute(int offset) { + int readOffset = offset + 10; + int codeLength = (int) u4At(readOffset); + readOffset += (4 + codeLength); + int exceptionTableLength = u2At(readOffset); + readOffset += 2; + if (exceptionTableLength != 0) { + for (int i = 0; i < exceptionTableLength; i++) { + readOffset += 8; + } + } + int attributesCount = u2At(readOffset); + readOffset += 2; + for (int i = 0; i < attributesCount; i++) { + int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; + char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + if (CharOperation.equals(attributeName, AttributeNamesConstants.LocalVariableTableName)) { + decodeLocalVariableAttribute(readOffset, codeLength); + } + readOffset += (6 + u4At(readOffset + 2)); + } +} +private void decodeLocalVariableAttribute(int offset, int codeLength) { + int readOffset = offset + 6; + final int length = u2At(readOffset); + if (length != 0) { + readOffset += 2; + this.argumentNames = new char[length][]; + this.argumentNamesIndex = 0; + for (int i = 0; i < length; i++) { + int startPC = u2At(readOffset); + if (startPC == 0) { + int nameIndex = u2At(4 + readOffset); + int utf8Offset = constantPoolOffsets[nameIndex] - structOffset; + char[] localVariableName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + if (!CharOperation.equals(localVariableName, ConstantPool.This)) { + this.argumentNames[this.argumentNamesIndex++] = localVariableName; + } + } else { + break; + } + readOffset += 10; + } + if (this.argumentNamesIndex != this.argumentNames.length) { + // resize + System.arraycopy(this.argumentNames, 0, (this.argumentNames = new char[this.argumentNamesIndex][]), 0, this.argumentNamesIndex); + } + } +} } Index: model/org/eclipse/jdt/internal/core/BinaryMethod.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java,v retrieving revision 1.92 diff -u -r1.92 BinaryMethod.java --- model/org/eclipse/jdt/internal/core/BinaryMethod.java 14 Feb 2007 14:55:50 -0000 1.92 +++ model/org/eclipse/jdt/internal/core/BinaryMethod.java 16 Feb 2007 17:37:49 -0000 @@ -173,50 +173,50 @@ if ((modifiers & ClassFileConstants.AccSynthetic) != 0) { return this.parameterNames = getRawParameterNames(paramCount); } - String javadocContents = null; - IType declaringType = this.getDeclaringType(); + String javadocContents = null; + IType declaringType = this.getDeclaringType(); PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject()); - synchronized (projectInfo.javadocCache) { - javadocContents = (String) projectInfo.javadocCache.get(declaringType); - if (javadocContents == null) { - projectInfo.javadocCache.put(declaringType, BinaryType.EMPTY_JAVADOC); - } - } - if (javadocContents == null) { - long timeOut = 50; // default value - try { - String option = this.getJavaProject().getOption(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, true); - if (option != null) { - timeOut = Long.parseLong(option); - } - } catch(NumberFormatException e) { - // ignore - } - if (timeOut == 0) { - // don't try to fetch the values - return this.parameterNames = getRawParameterNames(paramCount); - } - final class ParametersNameCollector { - String javadoc; - public void setJavadoc(String s) { - this.javadoc = s; - } - public String getJavadoc() { - return this.javadoc; - } - } - /* - * The declaring type is not in the cache yet. The thread wil retrieve the javadoc contents - */ - final ParametersNameCollector nameCollector = new ParametersNameCollector(); + synchronized (projectInfo.javadocCache) { + javadocContents = (String) projectInfo.javadocCache.get(declaringType); + if (javadocContents == null) { + projectInfo.javadocCache.put(declaringType, BinaryType.EMPTY_JAVADOC); + } + } + if (javadocContents == null) { + long timeOut = 50; // default value + try { + String option = this.getJavaProject().getOption(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, true); + if (option != null) { + timeOut = Long.parseLong(option); + } + } catch(NumberFormatException e) { + // ignore + } + if (timeOut == 0) { + // don't try to fetch the values + return this.parameterNames = getRawParameterNames(paramCount); + } + final class ParametersNameCollector { + String javadoc; + public void setJavadoc(String s) { + this.javadoc = s; + } + public String getJavadoc() { + return this.javadoc; + } + } + /* + * The declaring type is not in the cache yet. The thread wil retrieve the javadoc contents + */ + final ParametersNameCollector nameCollector = new ParametersNameCollector(); Thread collect = new Thread() { public void run() { try { // this call has a side-effect on the per project info cache nameCollector.setJavadoc(BinaryMethod.this.getAttachedJavadoc(null)); - } catch (JavaModelException e) { - // ignore - } + } catch (JavaModelException e) { + // ignore + } synchronized(nameCollector) { nameCollector.notify(); } @@ -231,17 +231,25 @@ } } javadocContents = nameCollector.getJavadoc(); - } else if (javadocContents != BinaryType.EMPTY_JAVADOC){ - // need to extract the part relative to the binary method since javadoc contains the javadoc for the declaring type - try { - javadocContents = extractJavadoc(declaringType, javadocContents); - } catch(JavaModelException e) { - // ignore - } - } else { - // we don't want to set the parameter names - return getRawParameterNames(paramCount); - } + } else if (javadocContents != BinaryType.EMPTY_JAVADOC){ + // need to extract the part relative to the binary method since javadoc contains the javadoc for the declaring type + try { + javadocContents = extractJavadoc(declaringType, javadocContents); + } catch(JavaModelException e) { + // ignore + } + } else { + // let's see if we can retrieve them from the debug infos + char[][] argumentNames = info.getArgumentNames(); + if (argumentNames != null && argumentNames.length == paramCount) { + String[] names = new String[paramCount]; + for (int i = 0; i < paramCount; i++) { + names[i] = new String(argumentNames[i]); + } + return this.parameterNames = names; + } + return getRawParameterNames(paramCount); + } if (javadocContents != null && javadocContents != BinaryType.EMPTY_JAVADOC) { final int indexOfOpenParen = javadocContents.indexOf('('); if (indexOfOpenParen != -1) { @@ -268,6 +276,15 @@ } } } + // let's see if we can retrieve them from the debug infos + char[][] argumentNames = info.getArgumentNames(); + if (argumentNames != null && argumentNames.length == paramCount) { + String[] names = new String[paramCount]; + for (int i = 0; i < paramCount; i++) { + names[i] = new String(argumentNames[i]); + } + return this.parameterNames = names; + } } // if still no parameter names, produce fake ones return this.parameterNames = getRawParameterNames(paramCount);