>
+private static void appendArgumentSimpleNames(char[] name, int start, int end, StringBuffer buffer) {
+ buffer.append('<');
+ int depth = 0;
+ int argumentStart = -1;
+ int argumentCount = 0;
+ for (int i = start; i <= end; i++) {
+ switch(name[i]) {
+ case '<' :
+ depth++;
+ if (depth == 1) {
+ argumentStart = i+1;
+ }
+ break;
+ case '>' :
+ if (depth == 1) {
+ if (argumentCount > 0) buffer.append(',');
+ appendSimpleName(name, argumentStart, i-1, buffer);
+ argumentCount++;
+ }
+ depth--;
+ break;
+ case ',' :
+ if (depth == 1) {
+ if (argumentCount > 0) buffer.append(',');
+ appendSimpleName(name, argumentStart, i-1, buffer);
+ argumentCount++;
+ argumentStart = i+1;
+ }
+ break;
+ }
+ }
+ buffer.append('>');
+}
+/**
+ * Returns all segments of the given dot-separated qualified name.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ *
+ * For example:
+ *
+ *
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames({}) -> {}
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'u', 't', 'i', 'l', '.', 'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '>'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'L', 'i', 's', 't', '<', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g'}}
+ *
+ *
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ * @since 2.0
+ */
+public static char[][] getSimpleNames(char[] name) {
+ int length = name == null ? 0 : name.length;
+ if (length == 0)
+ return CharOperation.NO_CHAR_CHAR;
+
+ int wordCount = 1;
+ countingWords: for (int i = 0; i < length; i++)
+ switch(name[i]) {
+ case C_DOT:
+ wordCount++;
+ break;
+ case C_GENERIC_START:
+ break countingWords;
+ }
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (name[i] == C_GENERIC_START) break;
+ if (name[i] == C_DOT) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(
+ name,
+ last,
+ split[currentWord++],
+ 0,
+ i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[length - last];
+ System.arraycopy(name, last, split[currentWord], 0, length - last);
+ return split;
+}
+/**
+ * Returns all segments of the given dot-separated qualified name.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ *
+ * For example:
+ *
+ *
+ * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
+ * getSimpleNames("Object") -> {"Object"}
+ * getSimpleNames("") -> {}
+ * getSimpleNames("java.util.List") -> {"java", "lang", "List
+ *
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * @exception NullPointerException if name is null
+ */
+public static String[] getSimpleNames(String name) {
+ return CharOperation.toStrings(getSimpleNames(name.toCharArray()));
+}
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ *
+ * For example:
+ *
+ *
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ *
+ *
+ *
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @return the char array representation of the method signature
+ *
+ * @since 2.0
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+ return toCharArray(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ *
+ * For example:
+ *
+ *
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ *
+ *
+ *
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @param isVargArgs true
if the last argument should be displayed as a
+ * variable argument, false
otherwise.
+ * @return the char array representation of the method signature
+ *
+ * @since 3.1
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVargArgs) {
+ int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
+ if (firstParen == -1) {
+ throw new IllegalArgumentException();
+ }
+
+ StringBuffer buffer = new StringBuffer(methodSignature.length + 10);
+
+ // return type
+ if (includeReturnType) {
+ char[] rts = getReturnType(methodSignature);
+ appendTypeSignature(rts, 0 , fullyQualifyTypeNames, buffer);
+ buffer.append(' ');
+ }
+
+ // selector
+ if (methodName != null) {
+ buffer.append(methodName);
+ }
+
+ // parameters
+ buffer.append('(');
+ char[][] pts = getParameterTypes(methodSignature);
+ for (int i = 0, max = pts.length; i < max; i++) {
+ if (i == max - 1) {
+ appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer, isVargArgs);
+ } else {
+ appendTypeSignature(pts[i], 0 , fullyQualifyTypeNames, buffer);
+ }
+ if (parameterNames != null) {
+ buffer.append(' ');
+ buffer.append(parameterNames[i]);
+ }
+ if (i != pts.length - 1) {
+ buffer.append(',');
+ buffer.append(' ');
+ }
+ }
+ buffer.append(')');
+ char[] result = new char[buffer.length()];
+ buffer.getChars(0, buffer.length(), result, 0);
+ return result;
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ *
+ *
+ * For example:
+ *
+ *
+ * toString({'[', 'L', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', ';'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '[', ']'}
+ * toString({'I'}) -> {'i', 'n', 't'}
+ * toString({'+', 'L', 'O', 'b', 'j', 'e', 'c', 't', ';'}) -> {'?', ' ', 'e', 'x', 't', 'e', 'n', 'd', 's', ' ', 'O', 'b', 'j', 'e', 'c', 't'}
+ *
+ *
+ *
+ *
+ * Note: This method assumes that a type signature containing a '$'
+ * is an inner type signature. While this is correct in most cases, someone could
+ * define a non-inner type name containing a '$'
. Handling this
+ * correctly in all cases would have required resolving the signature, which
+ * generally not feasible.
+ *
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ *
+ * @since 2.0
+ */
+public static char[] toCharArray(char[] signature) throws IllegalArgumentException {
+ int sigLength = signature.length;
+ if (sigLength == 0 || signature[0] == C_PARAM_START || signature[0] == C_GENERIC_START) {
+ return toCharArray(signature, CharOperation.NO_CHAR, null, true, true);
+ }
+
+ StringBuffer buffer = new StringBuffer(signature.length + 10);
+ appendTypeSignature(signature, 0, true, buffer);
+ char[] result = new char[buffer.length()];
+ buffer.getChars(0, buffer.length(), result, 0);
+ return result;
+}
+
+/**
+ * Scans the given string for a type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature
+ * @see #scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+/**
+ * Scans the given string for a type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @param isVarArgs true
if the type must be displayed as a
+ * variable argument, false
otherwise. In this case, the type must be an array type
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type signature, or if isVarArgs is true
,
+ * and the type is not an array type signature.
+ * @see #scanTypeSignature(char[], int)
+ */
+private static int appendTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
+ // need a minimum 1 char
+ if (start >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (isVarArgs) {
+ switch (c) {
+ case C_ARRAY :
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, true);
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ case C_TYPE_VARIABLE :
+ case C_BOOLEAN :
+ case C_BYTE :
+ case C_CHAR :
+ case C_DOUBLE :
+ case C_FLOAT :
+ case C_INT :
+ case C_LONG :
+ case C_SHORT :
+ case C_VOID :
+ case C_STAR:
+ case C_EXTENDS:
+ case C_SUPER:
+ default:
+ throw new IllegalArgumentException(); // a var args is an array type
+ }
+ } else {
+ switch (c) {
+ case C_ARRAY :
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+ case C_RESOLVED :
+ case C_UNRESOLVED :
+ return appendClassTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+ case C_TYPE_VARIABLE :
+ int e = scanTypeVariableSignature(string, start);
+ buffer.append(CharOperation.subarray(string, start + 1, e));
+ return e;
+ case C_BOOLEAN :
+ buffer.append(BOOLEAN);
+ return start;
+ case C_BYTE :
+ buffer.append(BYTE);
+ return start;
+ case C_CHAR :
+ buffer.append(CHAR);
+ return start;
+ case C_DOUBLE :
+ buffer.append(DOUBLE);
+ return start;
+ case C_FLOAT :
+ buffer.append(FLOAT);
+ return start;
+ case C_INT :
+ buffer.append(INT);
+ return start;
+ case C_LONG :
+ buffer.append(LONG);
+ return start;
+ case C_SHORT :
+ buffer.append(SHORT);
+ return start;
+ case C_VOID :
+ buffer.append(VOID);
+ return start;
+ case C_STAR:
+ case C_EXTENDS:
+ case C_SUPER:
+ return appendTypeArgumentSignature(string, start, fullyQualifyTypeNames, buffer);
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+}
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see #scanArrayTypeSignature(char[], int)
+ */
+private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ return appendArrayTypeSignature(string, start, fullyQualifyTypeNames, buffer, false);
+}
+/**
+ * Scans the given string for an array type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param isVarArgs true
if the array type must be displayed as a
+ * variable argument, false
otherwise
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not an array type signature
+ * @see #scanArrayTypeSignature(char[], int)
+ */
+private static int appendArrayTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer, boolean isVarArgs) {
+ // need a minimum 2 char
+ if (start >= string.length - 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (c != C_ARRAY) { //$NON-NLS-1$
+ throw new IllegalArgumentException();
+ }
+ int e = appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+ if (isVarArgs) {
+ buffer.append('.').append('.').append('.');
+ } else {
+ buffer.append('[').append(']');
+ }
+ return e;
+}
+/**
+ * Scans the given string for a class type signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a class type signature
+ * @see #scanClassTypeSignature(char[], int)
+ */
+private static int appendClassTypeSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ // need a minimum 3 chars "Lx;"
+ if (start >= string.length - 2) {
+ throw new IllegalArgumentException();
+ }
+ // must start in "L" or "Q"
+ char c = string[start];
+ if (c != C_RESOLVED && c != C_UNRESOLVED) {
+ throw new IllegalArgumentException();
+ }
+ boolean resolved = (c == C_RESOLVED);
+ boolean removePackageQualifiers = !fullyQualifyTypeNames;
+ if (!resolved) {
+ // keep everything in an unresolved name
+ removePackageQualifiers = false;
+ }
+ int p = start + 1;
+ int checkpoint = buffer.length();
+ while (true) {
+ if (p >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ c = string[p];
+ switch(c) {
+ case C_SEMICOLON :
+ // all done
+ return p;
+ case C_GENERIC_START :
+ int e = appendTypeArgumentSignatures(string, p, fullyQualifyTypeNames, buffer);
+ // once we hit type arguments there are no more package prefixes
+ removePackageQualifiers = false;
+ p = e;
+ break;
+ case C_DOT :
+ if (removePackageQualifiers) {
+ // erase package prefix
+ buffer.setLength(checkpoint);
+ } else {
+ buffer.append('.');
+ }
+ break;
+ case '/' :
+ if (removePackageQualifiers) {
+ // erase package prefix
+ buffer.setLength(checkpoint);
+ } else {
+ buffer.append('/');
+ }
+ break;
+ case C_DOLLAR :
+ if (resolved) {
+ // once we hit "$" there are no more package prefixes
+ removePackageQualifiers = false;
+ /**
+ * Convert '$' in resolved type signatures into '.'.
+ * NOTE: This assumes that the type signature is an inner type
+ * signature. This is true in most cases, but someone can define a
+ * non-inner type name containing a '$'.
+ */
+ buffer.append('.');
+ }
+ break;
+ default :
+ buffer.append(c);
+ }
+ p++;
+ }
+}
+
+/**
+ * Scans the given string for a list of type arguments signature starting at the
+ * given index and appends it to the given buffer, and returns the index of the
+ * last character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a list of type argument
+ * signatures
+ * @see #scanTypeArgumentSignatures(char[], int)
+ */
+private static int appendTypeArgumentSignatures(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ // need a minimum 2 char "<>"
+ if (start >= string.length - 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (c != C_GENERIC_START) {
+ throw new IllegalArgumentException();
+ }
+ buffer.append('<');
+ int p = start + 1;
+ int count = 0;
+ while (true) {
+ if (p >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ c = string[p];
+ if (c == C_GENERIC_END) {
+ buffer.append('>');
+ return p;
+ }
+ if (count != 0) {
+ buffer.append(',');
+ }
+ int e = appendTypeArgumentSignature(string, p, fullyQualifyTypeNames, buffer);
+ count++;
+ p = e + 1;
+ }
+}
+
+/**
+ * Scans the given string for a type argument signature starting at the given
+ * index and appends it to the given buffer, and returns the index of the last
+ * character.
+ *
+ * @param string the signature string
+ * @param start the 0-based character index of the first character
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param buffer the string buffer to append to
+ * @return the 0-based character index of the last character
+ * @exception IllegalArgumentException if this is not a type argument signature
+ * @see #scanTypeArgumentSignature(char[], int)
+ */
+private static int appendTypeArgumentSignature(char[] string, int start, boolean fullyQualifyTypeNames, StringBuffer buffer) {
+ // need a minimum 1 char
+ if (start >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ switch(c) {
+ case C_STAR :
+ buffer.append('?');
+ return start;
+ case C_EXTENDS :
+ buffer.append("? extends "); //$NON-NLS-1$
+ return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+ case C_SUPER :
+ buffer.append("? super "); //$NON-NLS-1$
+ return appendTypeSignature(string, start + 1, fullyQualifyTypeNames, buffer);
+ default :
+ return appendTypeSignature(string, start, fullyQualifyTypeNames, buffer);
+ }
+}
+
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ *
+ * For example:
+ *
+ *
+ * toQualifiedName({{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{}}) -> {}
+ *
+ *
+ *
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ *
+ * @since 2.0
+ */
+public static char[] toQualifiedName(char[][] segments) {
+ int length = segments.length;
+ if (length == 0) return CharOperation.NO_CHAR;
+ if (length == 1) return segments[0];
+
+ int resultLength = 0;
+ for (int i = 0; i < length; i++) {
+ resultLength += segments[i].length+1;
+ }
+ resultLength--;
+ char[] result = new char[resultLength];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
+ char[] segment = segments[i];
+ int segmentLength = segment.length;
+ System.arraycopy(segment, 0, result, index, segmentLength);
+ index += segmentLength;
+ if (i != length-1) {
+ result[index++] = C_DOT;
+ }
+ }
+ return result;
+}
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ *
+ * For example:
+ *
+ *
+ * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
+ * toQualifiedName(new String[] {"Object"}) -> "Object"
+ * toQualifiedName(new String[0]) -> ""
+ *
+ *
+ *
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ */
+public static String toQualifiedName(String[] segments) {
+ int length = segments.length;
+ char[][] charArrays = new char[length][];
+ for (int i = 0; i < length; i++) {
+ charArrays[i] = segments[i].toCharArray();
+ }
+ return new String(toQualifiedName(charArrays));
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ *
+ *
+ * For example:
+ *
+ *
+ * toString("[Ljava.lang.String;") -> "java.lang.String[]"
+ * toString("I") -> "int"
+ * toString("+QObject;") -> "? extends Object"
+ *
+ *
+ *
+ *
+ * Note: This method assumes that a type signature containing a '$'
+ * is an inner type signature. While this is correct in most cases, someone could
+ * define a non-inner type name containing a '$'
. Handling this
+ * correctly in all cases would have required resolving the signature, which
+ * generally not feasible.
+ *
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ * correct
+ */
+public static String toString(String signature) throws IllegalArgumentException {
+ return new String(toCharArray(signature.toCharArray()));
+}
+/**
+ * Converts the given method signature to a readable string. The method signature is expected to
+ * be dot-based.
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @see #toCharArray(char[], char[], char[][], boolean, boolean)
+ * @return the string representation of the method signature
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+ return toString(methodSignature, methodName, parameterNames, fullyQualifyTypeNames, includeReturnType, false);
+}
+/**
+ * Converts the given method signature to a readable string. The method signature is expected to
+ * be dot-based.
+ *
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or
+ * null
if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or
+ * null
if no parameter names are to be included; if supplied,
+ * the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames true
if type names should be fully
+ * qualified, and false
to use only simple names
+ * @param includeReturnType true
if the return type is to be
+ * included
+ * @param isVarArgs true
if the last argument should be displayed as a
+ * variable argument, false
otherwise
+ * @see #toCharArray(char[], char[], char[][], boolean, boolean)
+ * @return the string representation of the method signature
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType, boolean isVarArgs) {
+ char[][] params;
+ if (parameterNames == null) {
+ params = null;
+ } else {
+ int paramLength = parameterNames.length;
+ params = new char[paramLength][];
+ for (int i = 0; i < paramLength; i++) {
+ params[i] = parameterNames[i].toCharArray();
+ }
+ }
+ return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType, isVarArgs));
+}
+}
diff --git a/src/org/eclipse/jdt/core/compiler/CharOperation.java b/src/org/eclipse/jdt/core/compiler/CharOperation.java
index 07d23e3..b21cdf4 100644
--- a/src/org/eclipse/jdt/core/compiler/CharOperation.java
+++ b/src/org/eclipse/jdt/core/compiler/CharOperation.java
@@ -28,6 +28,12 @@ public final class CharOperation {
public static final char[][] NO_CHAR_CHAR = new char[0][];
/**
+ * Constant for an empty String array.
+ * @since 3.1
+ */
+ public static final String[] NO_STRINGS = new String[0];
+
+ /**
* Answers a new array with appending the suffix character at the end of the array.
*
*
@@ -171,13 +177,14 @@ public final class CharOperation {
* @since 3.0
*/
public static String[] charArrayToStringArray(char[][] charArrays) {
- if (charArrays == null) {
+ if (charArrays == null)
return null;
- }
- String[] strings= new String[charArrays.length];
- for (int i= 0; i < charArrays.length; i++) {
+ int length = charArrays.length;
+ if (length == 0)
+ return NO_STRINGS;
+ String[] strings= new String[length];
+ for (int i= 0; i < length; i++)
strings[i]= new String(charArrays[i]);
- }
return strings;
}
/**
@@ -490,7 +497,7 @@ public final class CharOperation {
/**
* Answers the concatenation of the three arrays inserting the sep1 character between the
- * two arrays and sep2 between the last two.
+ * first two arrays and sep2 between the last two.
* It answers null if the three arrays are null.
* If the first array is null, then it answers the concatenation of second and third inserting
* the sep2 character between them.
@@ -867,6 +874,40 @@ public final class CharOperation {
return true;
return false;
}
+
+ /**
+ * Answers true if the array contains an occurrence of one of the characters, false otherwise.
+ *
+ *
+ *
+ * For example:
+ *
+ *
+ * characters = { 'c', 'd' }
+ * array = { 'a', ' b' }
+ * result => false
+ *
+ *
+ *
+ * characters = { 'c', 'd' }
+ * array = { 'a', ' b', 'c' }
+ * result => true
+ *
+ *
+ *
+ *
+ * @param characters the characters to search
+ * @param array the array in which the search is done
+ * @return true if the array contains an occurrence of one of the characters, false otherwise.
+ * @throws NullPointerException if array is null.
+ */
+ public static final boolean contains(char[] characters, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ for (int j = characters.length; --j >= 0;)
+ if (array[i] == characters[j])
+ return true;
+ return false;
+ }
/**
* Answers a deep copy of the toCopy array.
@@ -2269,6 +2310,58 @@ public final class CharOperation {
System.arraycopy(array, inStart, result, outStart, max - inStart);
return result;
}
+
+ /**
+ * Replace all occurrence of the character to be replaced with the remplacement character
+ * in a copy of the given array. Returns the given array if no occurrences of the character
+ * to be replaced are found.
+ *
+ *
+ * For example:
+ *
+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'b'
+ * replacementChar = 'a'
+ * result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
+ *
+ *
+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'c'
+ * replacementChar = 'a'
+ * result => The original array that remains unchanged.
+ *
+ *
+ *
+ *
+ * @param array the given array
+ * @param toBeReplaced the character to be replaced
+ * @param replacementChar the replacement character
+ * @throws NullPointerException if the given array is null
+ * @since 3.1
+ */
+ public static final char[] replaceOnCopy(
+ char[] array,
+ char toBeReplaced,
+ char replacementChar) {
+
+ char[] result = null;
+ for (int i = 0, length = array.length; i < length; i++) {
+ char c = array[i];
+ if (c == toBeReplaced) {
+ if (result == null) {
+ result = new char[length];
+ System.arraycopy(array, 0, result, 0, i);
+ }
+ result[i] = replacementChar;
+ } else if (result != null) {
+ result[i] = c;
+ }
+ }
+ if (result == null) return array;
+ return result;
+ }
/**
* Return a new array which is the split of the given array using the given divider and triming each subarray to remove
@@ -2677,7 +2770,9 @@ public final class CharOperation {
* @since 3.0
*/
final static public String[] toStrings(char[][] array) {
+ if (array == null) return NO_STRINGS;
int length = array.length;
+ if (length == 0) return NO_STRINGS;
String[] result = new String[length];
for (int i = 0; i < length; i++)
result[i] = new String(array[i]);
diff --git a/src/org/eclipse/jdt/core/compiler/IProblem.java b/src/org/eclipse/jdt/core/compiler/IProblem.java
index 7be59f1..48c5422 100644
--- a/src/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/src/org/eclipse/jdt/core/compiler/IProblem.java
@@ -69,6 +69,9 @@
* JavadocInvalidTag
* JavadocMessagePrefix
* EmptyControlFlowStatement
+ * IBM Corporation - added the following constants
+ * IllegalUsageOfQualifiedTypeReference
+ * InvalidDigit
****************************************************************************/
package org.eclipse.jdt.core.compiler;
@@ -229,7 +232,7 @@ public interface IProblem {
int InternalTypeNameProvided = TypeRelated + 6;
/** @since 2.1 */
int UnusedPrivateType = Internal + TypeRelated + 7;
-
+
int IncompatibleTypesInEqualityOperator = TypeRelated + 15;
int IncompatibleTypesInConditionalOperator = TypeRelated + 16;
int TypeMismatch = TypeRelated + 17;
@@ -301,42 +304,21 @@ public interface IProblem {
int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
// variable hiding
- /**
- * The local variable {0} is hiding another local variable defined in an enclosing type scope
- * @since 3.0
- */
+ /** @since 3.0 */
int LocalVariableHidingLocalVariable = Internal + 90;
-
- /**
- * The local variable {0} is hiding the field {1}.{2}
- * @since 3.0
- */
+ /** @since 3.0 */
int LocalVariableHidingField = Internal + FieldRelated + 91;
-
- /**
- * The field {0}.{1} is hiding another local variable defined in an enclosing type scope
- * @since 3.0
- */
+ /** @since 3.0 */
int FieldHidingLocalVariable = Internal + FieldRelated + 92;
-
- /**
- * The field {0}.{1} is hiding the field {2}.{3}
- * @since 3.0
- */
+ /** @since 3.0 */
int FieldHidingField = Internal + FieldRelated + 93;
-
- /**
- * The argument {0} is hiding another local variable defined in an enclosing type scope
- * @since 3.0
- */
+ /** @since 3.0 */
int ArgumentHidingLocalVariable = Internal + 94;
-
- /**
- * The argument {0} is hiding the field {2}.{3}
- * @since 3.0
- */
+ /** @since 3.0 */
int ArgumentHidingField = Internal + 95;
-
+ /** @since 3.1 */
+ int MissingSerialVersion = Internal + 96;
+
// methods
int UndefinedMethod = MethodRelated + 100;
int NotVisibleMethod = MethodRelated + 101;
@@ -361,7 +343,6 @@ public interface IProblem {
/** @since 3.0 */
int IndirectAccessToStaticMethod = Internal + MethodRelated + 119;
-
// constructors
int UndefinedConstructor = ConstructorRelated + 130;
int NotVisibleConstructor = ConstructorRelated + 131;
@@ -445,7 +426,7 @@ public interface IProblem {
/** @since 3.0 */
int UnusedConstructorDeclaredThrownException = Internal + 186;
/** @since 3.0 */
- int InvalidCatchBlockSequence = Internal + TypeRelated + 187;
+ int InvalidCatchBlockSequence = Internal + TypeRelated + 187;
/** @since 3.0 */
int EmptyControlFlowStatement = Internal + TypeRelated + 188;
/** @since 3.0 */
@@ -462,6 +443,9 @@ public interface IProblem {
int InheritedFieldHidesEnclosingName = FieldRelated + 196;
int InheritedTypeHidesEnclosingName = TypeRelated + 197;
+ /** @since 3.1 */
+ int IllegalUsageOfQualifiedTypeReference = Internal + Syntax + 198;
+
// miscellaneous
int ThisInStaticContext = Internal + 200;
int StaticMethodRequested = Internal + MethodRelated + 201;
@@ -526,6 +510,8 @@ public interface IProblem {
int NullSourceString = Syntax + Internal + 258;
int UnterminatedString = Syntax + Internal + 259;
int UnterminatedComment = Syntax + Internal + 260;
+ /** @since 3.1 */
+ int InvalidDigit = Syntax + Internal + 262;
// type related problems
int InterfaceCannotHaveInitializers = TypeRelated + 300;
@@ -535,7 +521,8 @@ public interface IProblem {
int IllegalModifierForMemberClass = TypeRelated + 304;
int IllegalModifierForMemberInterface = TypeRelated + 305;
int IllegalModifierForLocalClass = TypeRelated + 306;
-
+ /** @since 3.1 */
+ int ForbiddenReference = TypeRelated + 307;
int IllegalModifierCombinationFinalAbstractForClass = TypeRelated + 308;
int IllegalVisibilityModifierForInterfaceMemberType = TypeRelated + 309;
int IllegalVisibilityModifierCombinationForMemberType = TypeRelated + 310;
@@ -559,19 +546,29 @@ public interface IProblem {
int PackageIsNotExpectedPackage = 328;
/** @since 2.1 */
int ObjectCannotHaveSuperTypes = 329;
+ /** @since 3.1 */
+ int ObjectMustBeClass = 330;
- // int InvalidSuperclassBase = TypeRelated + 329; // reserved to 334 included
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int SuperclassNotFound = TypeRelated + 329 + ProblemReasons.NotFound; // TypeRelated + 330
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int SuperclassNotVisible = TypeRelated + 329 + ProblemReasons.NotVisible; // TypeRelated + 331
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int SuperclassAmbiguous = TypeRelated + 329 + ProblemReasons.Ambiguous; // TypeRelated + 332
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int SuperclassInternalNameProvided = TypeRelated + 329 + ProblemReasons.InternalNameProvided; // TypeRelated + 333
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int SuperclassInheritedNameHidesEnclosingName = TypeRelated + 329 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 334
- // int InvalidInterfaceBase = TypeRelated + 334; // reserved to 339 included
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int InterfaceNotFound = TypeRelated + 334 + ProblemReasons.NotFound; // TypeRelated + 335
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int InterfaceNotVisible = TypeRelated + 334 + ProblemReasons.NotVisible; // TypeRelated + 336
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int InterfaceAmbiguous = TypeRelated + 334 + ProblemReasons.Ambiguous; // TypeRelated + 337
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int InterfaceInternalNameProvided = TypeRelated + 334 + ProblemReasons.InternalNameProvided; // TypeRelated + 338
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int InterfaceInheritedNameHidesEnclosingName = TypeRelated + 334 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 339
// field related problems
@@ -583,11 +580,15 @@ public interface IProblem {
int IllegalModifierCombinationFinalVolatileForField = FieldRelated + 345;
int UnexpectedStaticModifierForField = FieldRelated + 346;
- // int FieldTypeProblemBase = FieldRelated + 349; //reserved to 354
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int FieldTypeNotFound = FieldRelated + 349 + ProblemReasons.NotFound; // FieldRelated + 350
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int FieldTypeNotVisible = FieldRelated + 349 + ProblemReasons.NotVisible; // FieldRelated + 351
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int FieldTypeAmbiguous = FieldRelated + 349 + ProblemReasons.Ambiguous; // FieldRelated + 352
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int FieldTypeInternalNameProvided = FieldRelated + 349 + ProblemReasons.InternalNameProvided; // FieldRelated + 353
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int FieldTypeInheritedNameHidesEnclosingName = FieldRelated + 349 + ProblemReasons.InheritedNameHidesEnclosingName; // FieldRelated + 354
// method related problems
@@ -606,25 +607,37 @@ public interface IProblem {
int NativeMethodsCannotBeStrictfp = MethodRelated + 367;
int DuplicateModifierForArgument = MethodRelated + 368;
- // int ArgumentProblemBase = MethodRelated + 369; // reserved to 374 included.
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int ArgumentTypeNotFound = MethodRelated + 369 + ProblemReasons.NotFound; // MethodRelated + 370
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int ArgumentTypeNotVisible = MethodRelated + 369 + ProblemReasons.NotVisible; // MethodRelated + 371
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int ArgumentTypeAmbiguous = MethodRelated + 369 + ProblemReasons.Ambiguous; // MethodRelated + 372
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int ArgumentTypeInternalNameProvided = MethodRelated + 369 + ProblemReasons.InternalNameProvided; // MethodRelated + 373
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int ArgumentTypeInheritedNameHidesEnclosingName = MethodRelated + 369 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 374
- // int ExceptionTypeProblemBase = MethodRelated + 374; // reserved to 379 included.
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int ExceptionTypeNotFound = MethodRelated + 374 + ProblemReasons.NotFound; // MethodRelated + 375
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int ExceptionTypeNotVisible = MethodRelated + 374 + ProblemReasons.NotVisible; // MethodRelated + 376
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int ExceptionTypeAmbiguous = MethodRelated + 374 + ProblemReasons.Ambiguous; // MethodRelated + 377
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int ExceptionTypeInternalNameProvided = MethodRelated + 374 + ProblemReasons.InternalNameProvided; // MethodRelated + 378
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int ExceptionTypeInheritedNameHidesEnclosingName = MethodRelated + 374 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 379
- // int ReturnTypeProblemBase = MethodRelated + 379;
+ /** @deprecated - problem is no longer generated, UndefinedType is used instead */
int ReturnTypeNotFound = MethodRelated + 379 + ProblemReasons.NotFound; // MethodRelated + 380
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int ReturnTypeNotVisible = MethodRelated + 379 + ProblemReasons.NotVisible; // MethodRelated + 381
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int ReturnTypeAmbiguous = MethodRelated + 379 + ProblemReasons.Ambiguous; // MethodRelated + 382
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int ReturnTypeInternalNameProvided = MethodRelated + 379 + ProblemReasons.InternalNameProvided; // MethodRelated + 383
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int ReturnTypeInheritedNameHidesEnclosingName = MethodRelated + 379 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 384
// import related problems
@@ -633,16 +646,26 @@ public interface IProblem {
int CannotImportPackage = ImportRelated + 387;
int UnusedImport = ImportRelated + 388;
- // int ImportProblemBase = ImportRelated + 389;
int ImportNotFound = ImportRelated + 389 + ProblemReasons.NotFound; // ImportRelated + 390
+ /** @deprecated - problem is no longer generated, NotVisibleType is used instead */
int ImportNotVisible = ImportRelated + 389 + ProblemReasons.NotVisible; // ImportRelated + 391
+ /** @deprecated - problem is no longer generated, use AmbiguousType is used instead */
int ImportAmbiguous = ImportRelated + 389 + ProblemReasons.Ambiguous; // ImportRelated + 392
+ /** @deprecated - problem is no longer generated, use InternalTypeNameProvided is used instead */
int ImportInternalNameProvided = ImportRelated + 389 + ProblemReasons.InternalNameProvided; // ImportRelated + 393
+ /** @deprecated - problem is no longer generated, use InheritedTypeHidesEnclosingName is used instead */
int ImportInheritedNameHidesEnclosingName = ImportRelated + 389 + ProblemReasons.InheritedNameHidesEnclosingName; // ImportRelated + 394
+ /** @since 3.1 */
+ int InvalidTypeForStaticImport = ImportRelated + 391;
+
// local variable related problems
int DuplicateModifierForVariable = MethodRelated + 395;
int IllegalModifierForVariable = MethodRelated + 396;
+ /** @since 3.1 */
+ int LocalVariableCannotBeNull = MethodRelated + 397;
+ /** @since 3.1 */
+ int LocalVariableCanOnlyBeNull = MethodRelated + 398;
// method verifier problems
int AbstractMethodMustBeImplemented = MethodRelated + 400;
@@ -662,7 +685,9 @@ public interface IProblem {
int IncompatibleReturnTypeForNonInheritedInterfaceMethod = MethodRelated + 413;
/** @since 2.1 */
int IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod = MethodRelated + 414;
-
+ /** @since 3.0 */
+ int IllegalVararg = MethodRelated + 415;
+
// code snippet support
int CodeSnippetMissingClass = Internal + 420;
int CodeSnippetMissingMethod = Internal + 421;
@@ -684,6 +709,9 @@ public interface IProblem {
// assertion warning
int UseAssertAsAnIdentifier = Internal + 440;
+ // 1.5 features
+ int UseEnumAsAnIdentifier = Internal + 441;
+
// detected task
/** @since 2.1 */
int Task = Internal + 450;
@@ -720,9 +748,9 @@ public interface IProblem {
/** @since 3.0 */
int JavadocInvalidThrowsClassName = Javadoc + Internal + 481;
/** @since 3.0 */
- int JavadocMissingSeeReference = Javadoc + Internal + 482;
+ int JavadocMissingReference = Javadoc + Internal + 482;
/** @since 3.0 */
- int JavadocInvalidSeeReference = Javadoc + Internal + 483;
+ int JavadocInvalidReference = Javadoc + Internal + 483;
/** @since 3.0 */
int JavadocInvalidSeeHref = Javadoc + Internal + 484;
/** @since 3.0 */
@@ -794,7 +822,235 @@ public interface IProblem {
/** @since 3.0 */
int JavadocUnterminatedInlineTag = Javadoc + Internal + 512;
/** @since 3.0 */
- int JavadocMalformedSeeReference = Javadoc + Internal + 513;
+ int JavadocMissingHashCharacter = Javadoc + Internal + 513;
/** @since 3.0 */
- int JavadocMessagePrefix = Internal + 515;
-}
+ int JavadocMalformedSeeReference = Javadoc + Internal + 514;
+ /** @since 3.0 */
+ int JavadocEmptyReturnTag = Javadoc + Internal + 515;
+ /** @since 3.1 */
+ int JavadocInvalidValueReference = Javadoc + Internal + 516;
+ /** @since 3.1 */
+ int JavadocUnexpectedText = Javadoc + Internal + 517;
+ /** @since 3.1 */
+ int JavadocInvalidParamTagName = Javadoc + Internal + 518;
+ /** @since 3.1 */
+ int JavadocInvalidParamTagTypeParameter = Javadoc + Internal + 469;
+ /** @since 3.0 */
+ int JavadocMessagePrefix = Internal + 519;
+
+ /**
+ * Generics
+ */
+ /** @since 3.1 */
+ int DuplicateTypeVariable = Internal + 520;
+ /** @since 3.1 */
+ int IllegalTypeVariableSuperReference = Internal + 521;
+ /** @since 3.1 */
+ int TypeVariableReferenceFromStaticContext = Internal + 522;
+ /** @since 3.1 */
+ int ObjectCannotBeGeneric = Internal + 523;
+ /** @since 3.1 */
+ int NonGenericType = TypeRelated + 524;
+ /** @since 3.1 */
+ int IncorrectArityForParameterizedType = TypeRelated + 525;
+ /** @since 3.1 */
+ int TypeArgumentMismatch = TypeRelated + 526;
+ /** @since 3.1 */
+ int DuplicateMethodErasure = TypeRelated + 527;
+ /** @since 3.1 */
+ int ReferenceToForwardTypeVariable = TypeRelated + 528;
+ /** @since 3.1 */
+ int BoundsMustBeAnInterface = TypeRelated + 529;
+ /** @since 3.1 */
+ int UnsafeRawConstructorInvocation = TypeRelated + 530;
+ /** @since 3.1 */
+ int UnsafeRawMethodInvocation = TypeRelated + 531;
+ /** @since 3.1 */
+ int UnsafeRawConversion = TypeRelated + 532;
+ /** @since 3.1 */
+ int InvalidTypeVariableExceptionType = TypeRelated + 533;
+ /** @since 3.1 */
+ int InvalidParameterizedExceptionType = TypeRelated + 534;
+ /** @since 3.1 */
+ int IllegalGenericArray = TypeRelated + 535;
+ /** @since 3.1 */
+ int UnsafeRawFieldAssignment = TypeRelated + 536;
+ /** @since 3.1 */
+ int FinalBoundForTypeVariable = TypeRelated + 537;
+ /** @since 3.1 */
+ int UndefinedTypeVariable = Internal + 538;
+ /** @since 3.1 */
+ int SuperInterfacesCollide = TypeRelated + 539;
+ /** @since 3.1 */
+ int WildcardConstructorInvocation = TypeRelated + 540;
+ /** @since 3.1 */
+ int WildcardMethodInvocation = TypeRelated + 541;
+ /** @since 3.1 */
+ int WildcardFieldAssignment = TypeRelated + 542;
+ /** @since 3.1 */
+ int GenericMethodTypeArgumentMismatch = TypeRelated + 543;
+ /** @since 3.1 */
+ int GenericConstructorTypeArgumentMismatch = TypeRelated + 544;
+ /** @since 3.1 */
+ int UnsafeGenericCast = TypeRelated + 545;
+ /** @since 3.1 */
+ int IllegalInstanceofParameterizedType = Internal + 546;
+ /** @since 3.1 */
+ int IllegalInstanceofTypeParameter = Internal + 547;
+ /** @since 3.1 */
+ int NonGenericMethod = TypeRelated + 548;
+ /** @since 3.1 */
+ int IncorrectArityForParameterizedMethod = TypeRelated + 549;
+ /** @since 3.1 */
+ int ParameterizedMethodArgumentTypeMismatch = TypeRelated + 550;
+ /** @since 3.1 */
+ int NonGenericConstructor = TypeRelated + 551;
+ /** @since 3.1 */
+ int IncorrectArityForParameterizedConstructor = TypeRelated + 552;
+ /** @since 3.1 */
+ int ParameterizedConstructorArgumentTypeMismatch = TypeRelated + 553;
+ /** @since 3.1 */
+ int TypeArgumentsForRawGenericMethod = TypeRelated + 554;
+ /** @since 3.1 */
+ int TypeArgumentsForRawGenericConstructor = TypeRelated + 555;
+ /** @since 3.1 */
+ int SuperTypeUsingWildcard = TypeRelated + 556;
+ /** @since 3.1 */
+ int GenericTypeCannotExtendThrowable = TypeRelated + 557;
+ /** @since 3.1 */
+ int IllegalClassLiteralForTypeVariable = TypeRelated + 558;
+ /** @since 3.1 */
+ int UnsafeReturnTypeOverride = MethodRelated + 559;
+ /** @since 3.1 */
+ int MethodNameClash = MethodRelated + 560;
+ /** @since 3.1 */
+ int RawMemberTypeCannotBeParameterized = TypeRelated + 561;
+ /** @since 3.1 */
+ int MissingArgumentsForParameterizedMemberType = TypeRelated + 562;
+ /** @since 3.1 */
+ int StaticMemberOfParameterizedType = TypeRelated + 563;
+ /** @since 3.1 */
+ int BoundHasConflictingArguments = TypeRelated + 564;
+ /** @since 3.1 */
+ int DuplicateParameterizedMethods = MethodRelated + 565;
+
+ /**
+ * Foreach
+ */
+ /** @since 3.1 */
+ int IncompatibleTypesInForeach = TypeRelated + 580;
+ /** @since 3.1 */
+ int InvalidTypeForCollection = Internal + 581;
+
+ /**
+ * 1.5 Syntax errors (when source level < 1.5)
+ */
+ /** @since 3.1 */
+ int InvalidUsageOfTypeParameters = Syntax + Internal + 590;
+ /** @since 3.1 */
+ int InvalidUsageOfStaticImports = Syntax + Internal + 591;
+ /** @since 3.1 */
+ int InvalidUsageOfForeachStatements = Syntax + Internal + 592;
+ /** @since 3.1 */
+ int InvalidUsageOfTypeArguments = Syntax + Internal + 593;
+ /** @since 3.1 */
+ int InvalidUsageOfEnumDeclarations = Syntax + Internal + 594;
+ /** @since 3.1 */
+ int InvalidUsageOfVarargs = Syntax + Internal + 595;
+ /** @since 3.1 */
+ int InvalidUsageOfAnnotations = Syntax + Internal + 596;
+ /** @since 3.1 */
+ int InvalidUsageOfAnnotationDeclarations = Syntax + Internal + 597;
+
+ /**
+ * Annotation
+ */
+ /** @since 3.1 */
+ int IllegalModifierForAnnotationMethod = MethodRelated + 600;
+ /** @since 3.1 */
+ int IllegalExtendedDimensions = MethodRelated + 601;
+ /** @since 3.1 */
+ int InvalidFileNameForPackageAnnotations = Syntax + Internal + 602;
+ /** @since 3.1 */
+ int IllegalModifierForAnnotationType = TypeRelated + 603;
+ /** @since 3.1 */
+ int IllegalModifierForAnnotationMemberType = TypeRelated + 604;
+ /** @since 3.1 */
+ int InvalidAnnotationMemberType = TypeRelated + 605;
+ /** @since 3.1 */
+ int AnnotationCircularitySelfReference = TypeRelated + 606;
+ /** @since 3.1 */
+ int AnnotationCircularity = TypeRelated + 607;
+ /** @since 3.1 */
+ int DuplicateAnnotation = TypeRelated + 608;
+ /** @since 3.1 */
+ int MissingValueForAnnotationMember = TypeRelated + 609;
+ /** @since 3.1 */
+ int DuplicateAnnotationMember = Internal + 610;
+ /** @since 3.1 */
+ int UndefinedAnnotationMember = MethodRelated + 611;
+ /** @since 3.1 */
+ int AnnotationValueMustBeClassLiteral = Internal + 612;
+ /** @since 3.1 */
+ int AnnotationValueMustBeConstant = Internal + 613;
+ /** @since 3.1 */
+ int AnnotationFieldNeedConstantInitialization = Internal + 614;
+ /** @since 3.1 */
+ int IllegalModifierForAnnotationField = Internal + 615;
+ /** @since 3.1 */
+ int AnnotationCannotOverrideMethod = MethodRelated + 616;
+ /** @since 3.1 */
+ int AnnotationMembersCannotHaveParameters = Syntax + Internal + 617;
+ /** @since 3.1 */
+ int AnnotationMembersCannotHaveTypeParameters = Syntax + Internal + 618;
+ /** @since 3.1 */
+ int AnnotationTypeDeclarationCannotHaveSuperclass = Syntax + Internal + 619;
+ /** @since 3.1 */
+ int AnnotationTypeDeclarationCannotHaveSuperinterfaces = Syntax + Internal + 620;
+ /** @since 3.1 */
+ int DuplicateTargetInTargetAnnotation = Internal + 621;
+ /** @since 3.1 */
+ int DisallowedTargetForAnnotation = TypeRelated + 622;
+ /** @since 3.1 */
+ int MethodMustOverride = TypeRelated + 623;
+ /** @since 3.1 */
+ int AnnotationTypeDeclarationCannotHaveConstructor = Syntax + Internal + 624;
+
+ /**
+ * Corrupted binaries
+ */
+ /** @since 3.1 */
+ int CorruptedSignature = Internal + 700;
+
+ /**
+ * Enum
+ */
+ /** @since 3.1 */
+ int IllegalModifierForEnum = TypeRelated + 750;
+ /** @since 3.1 */
+ int IllegalModifierForEnumConstant = FieldRelated + 751;
+ /** @since 3.1 */
+ int IllegalModifierForLocalEnum = TypeRelated + 752;
+ /** @since 3.1 */
+ int IllegalModifierForMemberEnum = TypeRelated + 753;
+ /** @since 3.1 */
+ int CannotDeclareEnumSpecialMethod = MethodRelated + 754;
+ /** @since 3.1 */
+ int IllegalQualifiedEnumConstantLabel = FieldRelated + 755;
+ /** @since 3.1 */
+ int CannotExtendEnum = TypeRelated + 756;
+ /** @since 3.1 */
+ int CannotInvokeSuperConstructorInEnum = MethodRelated + 757;
+ /** @since 3.1 */
+ int EnumAbstractMethodMustBeImplemented = MethodRelated + 758;
+
+ /**
+ * Var args
+ */
+ /** @since 3.1 */
+ int IllegalExtendedDimensionsForVarArgs = Syntax + Internal + 800;
+ /** @since 3.1 */
+ int MethodVarargsArgumentNeedCast = MethodRelated + 801;
+ /** @since 3.1 */
+ int ConstructorVarargsArgumentNeedCast = ConstructorRelated + 802;
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/core/compiler/InvalidInputException.java b/src/org/eclipse/jdt/core/compiler/InvalidInputException.java
index 7055b43..508f522 100644
--- a/src/org/eclipse/jdt/core/compiler/InvalidInputException.java
+++ b/src/org/eclipse/jdt/core/compiler/InvalidInputException.java
@@ -16,8 +16,8 @@ package org.eclipse.jdt.core.compiler;
*/
public class InvalidInputException extends Exception {
- private static final long serialVersionUID = 2909732853499731592L; // backward compatible
-
+ private static final long serialVersionUID = 2909732853499731592L; // backward compatible
+
/**
* Creates a new exception with no detail message.
*/
diff --git a/src/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/src/org/eclipse/jdt/internal/compiler/ASTVisitor.java
index 9e1166d..1a105fb 100644
--- a/src/org/eclipse/jdt/internal/compiler/ASTVisitor.java
+++ b/src/org/eclipse/jdt/internal/compiler/ASTVisitor.java
@@ -30,33 +30,11 @@ public abstract class ASTVisitor {
public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
// do nothing by default
}
- public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
- // do nothing by default
- }
- public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
- // do nothing by default
- }
+ public void endVisit(
+ AnnotationMethodDeclaration annotationTypeDeclaration,
+ ClassScope classScope) {
+ // do nothing by default
+ }
public void endVisit(Argument argument, BlockScope scope) {
// do nothing by default
}
@@ -87,10 +65,10 @@ public abstract class ASTVisitor {
public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
// do nothing by default
}
- public void endVisit(Assignment assignment, BlockScope scope) {
+ public void endVisit(AssertStatement assertStatement, BlockScope scope) {
// do nothing by default
}
- public void endVisit(AssertStatement assertStatement, BlockScope scope) {
+ public void endVisit(Assignment assignment, BlockScope scope) {
// do nothing by default
}
public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
@@ -144,6 +122,9 @@ public abstract class ASTVisitor {
public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
// do nothing by default
}
+ public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+ // do nothing by default
+ }
public void endVisit(EqualExpression equalExpression, BlockScope scope) {
// do nothing by default
}
@@ -169,7 +150,7 @@ public abstract class ASTVisitor {
public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
// do nothing by default
}
- public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+ public void endVisit(ForeachStatement forStatement, BlockScope scope) {
// do nothing by default
}
public void endVisit(ForStatement forStatement, BlockScope scope) {
@@ -192,6 +173,33 @@ public abstract class ASTVisitor {
public void endVisit(IntLiteral intLiteral, BlockScope scope) {
// do nothing by default
}
+ public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ // do nothing by default
+ }
public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
// do nothing by default
}
@@ -201,6 +209,36 @@ public abstract class ASTVisitor {
public void endVisit(LongLiteral longLiteral, BlockScope scope) {
// do nothing by default
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(MarkerAnnotation annotation, BlockScope scope) {
+ // do nothing by default
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(MarkerAnnotation annotation, CompilationUnitScope scope) {
+ // do nothing by default
+ }
+ /**
+ * @param pair
+ * @param scope
+ */
+ public void endVisit(MemberValuePair pair, BlockScope scope) {
+ // do nothing by default
+ }
+ /**
+ * @param pair
+ * @param scope
+ */
+ public void endVisit(MemberValuePair pair, CompilationUnitScope scope) {
+ // do nothing by default
+ }
public void endVisit(MessageSend messageSend, BlockScope scope) {
// do nothing by default
}
@@ -210,12 +248,40 @@ public abstract class ASTVisitor {
public void endVisit(StringLiteralConcatenation literal, BlockScope scope) {
// do nothing by default
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(NormalAnnotation annotation, BlockScope scope) {
+ // do nothing by default
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(NormalAnnotation annotation, CompilationUnitScope scope) {
+ // do nothing by default
+ }
public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
// do nothing by default
}
public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
// do nothing by default
}
+ public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+ // do nothing by default
+ }
public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
// do nothing by default
}
@@ -255,6 +321,22 @@ public abstract class ASTVisitor {
public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
// do nothing by default
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(SingleMemberAnnotation annotation, BlockScope scope) {
+ // do nothing by default
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public void endVisit(SingleMemberAnnotation annotation, CompilationUnitScope scope) {
+ // do nothing by default
+ }
public void endVisit(
SingleNameReference singleNameReference,
BlockScope scope) {
@@ -311,48 +393,37 @@ public abstract class ASTVisitor {
CompilationUnitScope scope) {
// do nothing by default
}
+ public void endVisit(TypeParameter typeParameter, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(TypeParameter typeParameter, ClassScope scope) {
+ // do nothing by default
+ }
public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
// do nothing by default
}
public void endVisit(WhileStatement whileStatement, BlockScope scope) {
// do nothing by default
}
+ public void endVisit(Wildcard wildcard, BlockScope scope) {
+ // do nothing by default
+ }
+ public void endVisit(Wildcard wildcard, ClassScope scope) {
+ // do nothing by default
+ }
public boolean visit(
AllocationExpression allocationExpression,
BlockScope scope) {
return true; // do nothing by default, keep traversing
- // do nothing by default
}
public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
- public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
- return true; // do nothing by default, keep traversing
- }
- public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ public boolean visit(
+ AnnotationMethodDeclaration annotationTypeDeclaration,
+ ClassScope classScope) {
return true; // do nothing by default, keep traversing
- }
+ }
public boolean visit(Argument argument, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
@@ -383,10 +454,10 @@ public abstract class ASTVisitor {
public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
return true; // do nothing by default, keep traversing
}
- public boolean visit(Assignment assignment, BlockScope scope) {
+ public boolean visit(AssertStatement assertStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
- public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+ public boolean visit(Assignment assignment, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
@@ -440,10 +511,10 @@ public abstract class ASTVisitor {
public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
- public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+ public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
- public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+ public boolean visit(EqualExpression equalExpression, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
public boolean visit(
@@ -468,6 +539,9 @@ public abstract class ASTVisitor {
public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(ForeachStatement forStatement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
public boolean visit(ForStatement forStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
@@ -488,6 +562,33 @@ public abstract class ASTVisitor {
public boolean visit(IntLiteral intLiteral, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
@@ -497,6 +598,38 @@ public abstract class ASTVisitor {
public boolean visit(LongLiteral longLiteral, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
+ return true;
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(MarkerAnnotation annotation, CompilationUnitScope scope) {
+ return true;
+ }
+ /**
+ * @param pair
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(MemberValuePair pair, BlockScope scope) {
+ return true;
+ }
+ /**
+ * @param pair
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(MemberValuePair pair, CompilationUnitScope scope) {
+ return true;
+ }
public boolean visit(MessageSend messageSend, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
@@ -508,12 +641,40 @@ public abstract class ASTVisitor {
BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(NormalAnnotation annotation, BlockScope scope) {
+ return true;
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(NormalAnnotation annotation, CompilationUnitScope scope) {
+ return true;
+ }
public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
@@ -553,6 +714,22 @@ public abstract class ASTVisitor {
public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
+ return true;
+ }
+ /**
+ * @param annotation
+ * @param scope
+ * @since 3.1
+ */
+ public boolean visit(SingleMemberAnnotation annotation, CompilationUnitScope scope) {
+ return true;
+ }
public boolean visit(
SingleNameReference singleNameReference,
BlockScope scope) {
@@ -609,10 +786,22 @@ public abstract class ASTVisitor {
CompilationUnitScope scope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(TypeParameter typeParameter, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(TypeParameter typeParameter, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
public boolean visit(WhileStatement whileStatement, BlockScope scope) {
return true; // do nothing by default, keep traversing
}
+ public boolean visit(Wildcard wildcard, BlockScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
+ public boolean visit(Wildcard wildcard, ClassScope scope) {
+ return true; // do nothing by default, keep traversing
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ClassFile.java b/src/org/eclipse/jdt/internal/compiler/ClassFile.java
index e575af5..dbed323 100644
--- a/src/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/src/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -20,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -45,29 +46,285 @@ import org.eclipse.jdt.internal.compiler.util.Util;
*/
public class ClassFile
implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
- public SourceTypeBinding referenceBinding;
- public ConstantPool constantPool;
- public ClassFile enclosingClassFile;
- // used to generate private access methods
- public int produceDebugAttributes;
- public ReferenceBinding[] innerClassesBindings;
- public int numberOfInnerClasses;
- public byte[] header;
+ public static final int INITIAL_CONTENTS_SIZE = 400;
+ public static final int INITIAL_HEADER_SIZE = 1500;
+ public static final int INNER_CLASSES_SIZE = 5;
+
+ /**
+ * INTERNAL USE-ONLY
+ * Build all the directories and subdirectories corresponding to the packages names
+ * into the directory specified in parameters.
+ *
+ * outputPath is formed like:
+ * c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ * java\lang\String.class *
+ *
+ * @param outputPath java.lang.String
+ * @param relativeFileName java.lang.String
+ * @return java.lang.String
+ */
+ public static String buildAllDirectoriesInto(
+ String outputPath,
+ String relativeFileName)
+ throws IOException {
+ char fileSeparatorChar = File.separatorChar;
+ String fileSeparator = File.separator;
+ File f;
+ // First we ensure that the outputPath exists
+ outputPath = outputPath.replace('/', fileSeparatorChar);
+ // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+ if (outputPath.endsWith(fileSeparator)) {
+ outputPath = outputPath.substring(0, outputPath.length() - 1);
+ }
+ f = new File(outputPath);
+ if (f.exists()) {
+ if (!f.isDirectory()) {
+ System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
+ throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
+ }
+ } else {
+ // we have to create that directory
+ if (!f.mkdirs()) {
+ System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
+ throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
+ }
+ }
+ StringBuffer outDir = new StringBuffer(outputPath);
+ outDir.append(fileSeparator);
+ StringTokenizer tokenizer =
+ new StringTokenizer(relativeFileName, fileSeparator);
+ String token = tokenizer.nextToken();
+ while (tokenizer.hasMoreTokens()) {
+ f = new File(outDir.append(token).append(fileSeparator).toString());
+ if (f.exists()) {
+ // The outDir already exists, so we proceed the next entry
+ // System.out.println("outDir: " + outDir + " already exists.");
+ } else {
+ // Need to add the outDir
+ if (!f.mkdir()) {
+ System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
+ throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
+ }
+ }
+ token = tokenizer.nextToken();
+ }
+ // token contains the last one
+ return outDir.append(token).toString();
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * Request the creation of a ClassFile compatible representation of a problematic type
+ *
+ * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+ * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+ */
+ public static void createProblemType(
+ TypeDeclaration typeDeclaration,
+ CompilationResult unitResult) {
+ SourceTypeBinding typeBinding = typeDeclaration.binding;
+ ClassFile classFile = new ClassFile(typeBinding, null, true);
+
+ // TODO (olivier) handle cases where a field cannot be generated (name too long)
+ // TODO (olivier) handle too many methods
+ // inner attributes
+ if (typeBinding.isMemberType())
+ classFile.recordEnclosingTypeAttributes(typeBinding);
+
+ // add its fields
+ FieldBinding[] fields = typeBinding.fields;
+ if ((fields != null) && (fields != NoFields)) {
+ for (int i = 0, max = fields.length; i < max; i++) {
+ if (fields[i].constant() == null) {
+ FieldReference.getConstantFor(fields[i], null, false, null);
+ }
+ }
+ classFile.addFieldInfos();
+ } else {
+ // we have to set the number of fields to be equals to 0
+ classFile.contents[classFile.contentsOffset++] = 0;
+ classFile.contents[classFile.contentsOffset++] = 0;
+ }
+ // leave some space for the methodCount
+ classFile.setForMethodInfos();
+ // add its user defined methods
+ MethodBinding[] methods = typeBinding.methods;
+ AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+ int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+ int problemsLength;
+ IProblem[] problems = unitResult.getErrors();
+ if (problems == null) {
+ problems = new IProblem[0];
+ }
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ if (methods != null) {
+ if (typeBinding.isInterface()) {
+ // we cannot create problem methods for an interface. So we have to generate a clinit
+ // which should contain all the problem
+ classFile.addProblemClinit(problemsCopy);
+ for (int i = 0, max = methods.length; i < max; i++) {
+ MethodBinding methodBinding;
+ if ((methodBinding = methods[i]) != null) {
+ // find the corresponding method declaration
+ for (int j = 0; j < maxMethodDecl; j++) {
+ if ((methodDeclarations[j] != null)
+ && (methodDeclarations[j].binding == methods[i])) {
+ if (!methodBinding.isConstructor()) {
+ classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 0, max = methods.length; i < max; i++) {
+ MethodBinding methodBinding;
+ if ((methodBinding = methods[i]) != null) {
+ // find the corresponding method declaration
+ for (int j = 0; j < maxMethodDecl; j++) {
+ if ((methodDeclarations[j] != null)
+ && (methodDeclarations[j].binding == methods[i])) {
+ AbstractMethodDeclaration methodDecl;
+ if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+ classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+ } else {
+ classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ // add abstract methods
+ classFile.addDefaultAbstractMethods();
+ }
+ // propagate generation of (problem) member types
+ if (typeDeclaration.memberTypes != null) {
+ for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+ TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+ if (memberType.binding != null) {
+ classFile.recordNestedMemberAttribute(memberType.binding);
+ ClassFile.createProblemType(memberType, unitResult);
+ }
+ }
+ }
+ classFile.addAttributes();
+ unitResult.record(typeBinding.constantPoolName(), classFile);
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * Search the line number corresponding to a specific position
+ */
+ public static final int searchLineNumber(
+ int[] startLineIndexes,
+ int position) {
+ // this code is completely useless, but it is the same implementation than
+ // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
+ // if (startLineIndexes == null)
+ // return 1;
+ int length = startLineIndexes.length;
+ if (length == 0)
+ return 1;
+ int g = 0, d = length - 1;
+ int m = 0;
+ while (g <= d) {
+ m = (g + d) / 2;
+ if (position < startLineIndexes[m]) {
+ d = m - 1;
+ } else
+ if (position > startLineIndexes[m]) {
+ g = m + 1;
+ } else {
+ return m + 1;
+ }
+ }
+ if (position < startLineIndexes[m]) {
+ return m + 1;
+ }
+ return m + 2;
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * outputPath is formed like:
+ * c:\temp\ the last character is a file separator
+ * relativeFileName is formed like:
+ * java\lang\String.class
+ * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
+ * @param outputPath the output directory
+ * @param relativeFileName java.lang.String
+ * @param contents byte[]
+ *
+ */
+ public static void writeToDisk(
+ boolean generatePackagesStructure,
+ String outputPath,
+ String relativeFileName,
+ byte[] contents)
+ throws IOException {
+
+ BufferedOutputStream output = null;
+ if (generatePackagesStructure) {
+ output = new BufferedOutputStream(
+ new FileOutputStream(
+ new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
+ } else {
+ String fileName = null;
+ char fileSeparatorChar = File.separatorChar;
+ String fileSeparator = File.separator;
+ // First we ensure that the outputPath exists
+ outputPath = outputPath.replace('/', fileSeparatorChar);
+ // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+ int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
+ if (indexOfPackageSeparator == -1) {
+ if (outputPath.endsWith(fileSeparator)) {
+ fileName = outputPath + relativeFileName;
+ } else {
+ fileName = outputPath + fileSeparator + relativeFileName;
+ }
+ } else {
+ int length = relativeFileName.length();
+ if (outputPath.endsWith(fileSeparator)) {
+ fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+ } else {
+ fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+ }
+ }
+ output = new BufferedOutputStream(
+ new FileOutputStream(
+ new File(fileName)));
+ }
+ try {
+ output.write(contents);
+ } finally {
+ output.flush();
+ output.close();
+ }
+ }
+ public CodeStream codeStream;
+ public ConstantPool constantPool;
+ public int constantPoolOffset;
// the header contains all the bytes till the end of the constant pool
public byte[] contents;
+ public int contentsOffset;
+ protected boolean creatingProblemType;
+ public ClassFile enclosingClassFile;
+ public byte[] header;
// that collection contains all the remaining bytes of the .class file
public int headerOffset;
- public int contentsOffset;
- public int constantPoolOffset;
- public int methodCountOffset;
+ public ReferenceBinding[] innerClassesBindings;
public int methodCount;
- protected boolean creatingProblemType;
- public static final int INITIAL_CONTENTS_SIZE = 400;
- public static final int INITIAL_HEADER_SIZE = 1500;
+ public int methodCountOffset;
+ public int numberOfInnerClasses;
public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
- public static final int INNER_CLASSES_SIZE = 5;
- public CodeStream codeStream;
- protected int problemLine; // used to create line number attributes for problem methods
+ // used to generate private access methods
+ public int produceDebugAttributes;
+ public SourceTypeBinding referenceBinding;
public long targetJDK;
/**
@@ -91,7 +348,7 @@ public class ClassFile
ClassFile enclosingClassFile,
boolean creatingProblemType) {
- referenceBinding = aType;
+ this.referenceBinding = aType;
initByteArrays();
// generate the magic numbers inside the header
@@ -100,7 +357,8 @@ public class ClassFile
header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
- this.targetJDK = referenceBinding.scope.environment().options.targetJDK;
+ final CompilerOptions options = aType.scope.environment().options;
+ this.targetJDK = options.targetJDK;
header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
@@ -139,15 +397,15 @@ public class ClassFile
// now we continue to generate the bytes inside the contents array
contents[contentsOffset++] = (byte) (accessFlags >> 8);
contents[contentsOffset++] = (byte) accessFlags;
- int classNameIndex = constantPool.literalIndex(aType);
+ int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName());
contents[contentsOffset++] = (byte) (classNameIndex >> 8);
contents[contentsOffset++] = (byte) classNameIndex;
int superclassNameIndex;
if (aType.isInterface()) {
- superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+ superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
} else {
superclassNameIndex =
- (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+ (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName()));
}
contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
contents[contentsOffset++] = (byte) superclassNameIndex;
@@ -156,14 +414,14 @@ public class ClassFile
contents[contentsOffset++] = (byte) (interfacesCount >> 8);
contents[contentsOffset++] = (byte) interfacesCount;
for (int i = 0; i < interfacesCount; i++) {
- int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+ int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
contents[contentsOffset++] = (byte) interfaceIndex;
}
- produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
+ produceDebugAttributes = options.produceDebugAttributes;
innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
this.creatingProblemType = creatingProblemType;
- codeStream = new CodeStream(this);
+ codeStream = new CodeStream(this, this.targetJDK);
// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
@@ -284,14 +542,14 @@ public class ClassFile
for (int i = 0; i < numberOfInnerClasses; i++) {
ReferenceBinding innerClass = innerClassesBindings[i];
int accessFlags = innerClass.getAccessFlags();
- int innerClassIndex = constantPool.literalIndex(innerClass);
+ int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
// inner class index
contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
contents[contentsOffset++] = (byte) innerClassIndex;
// outer class index: anonymous and local have no outer class index
if (innerClass.isMemberType()) {
// member or member of local
- int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
+ int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
contents[contentsOffset++] = (byte) outerClassIndex;
} else {
@@ -312,15 +570,86 @@ public class ClassFile
// access flag
if (innerClass.isAnonymousType()) {
accessFlags |= AccPrivate;
- } else
- if (innerClass.isLocalType() && !innerClass.isMemberType()) {
- accessFlags |= AccPrivate;
- }
+ } else if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+ accessFlags |= AccPrivate;
+ } else if (innerClass.isMemberType() && (innerClass.isInterface() || innerClass.isAnnotationType())) {
+ accessFlags |= AccStatic; // implicitely static
+ }
contents[contentsOffset++] = (byte) (accessFlags >> 8);
contents[contentsOffset++] = (byte) accessFlags;
}
attributeNumber++;
}
+ // add signature attribute
+ char[] genericSignature = referenceBinding.genericSignature();
+ if (genericSignature != null) {
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 8 >= contents.length) {
+ resizeContents(8);
+ }
+ int signatureAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+ contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+ // the length of a signature attribute is equals to 2
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ int signatureIndex =
+ constantPool.literalIndex(genericSignature);
+ contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureIndex;
+ attributeNumber++;
+ }
+ if (targetJDK >= ClassFileConstants.JDK1_5
+ && (this.referenceBinding.isAnonymousType() || this.referenceBinding.isLocalType())) {
+ // add enclosing method attribute (1.5 mode only)
+ if (contentsOffset + 10 >= contents.length) {
+ resizeContents(10);
+ }
+ int enclosingMethodAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
+ contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
+ // the length of a signature attribute is equals to 2
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 4;
+
+ int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
+ contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
+ contents[contentsOffset++] = (byte) enclosingTypeIndex;
+ byte methodIndexByte1 = 0;
+ byte methodIndexByte2 = 0;
+ if (this.referenceBinding.scope != null) {
+ MethodScope methodScope = this.referenceBinding.scope.methodScope();
+ if (methodScope != null) {
+ ReferenceContext referenceContext = methodScope.referenceContext;
+ if (referenceContext instanceof AbstractMethodDeclaration) {
+ AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
+ MethodBinding methodBinding = methodDeclaration.binding;
+ int enclosingMethodIndex = constantPool.literalIndexForMethod(methodBinding.selector, methodBinding.signature());
+ methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
+ methodIndexByte2 = (byte) enclosingMethodIndex;
+ }
+ }
+ }
+ contents[contentsOffset++] = methodIndexByte1;
+ contents[contentsOffset++] = methodIndexByte2;
+ attributeNumber++;
+ }
+ if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+ TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+ if (typeDeclaration != null) {
+ final Annotation[] annotations = typeDeclaration.annotations;
+ if (annotations != null) {
+ attributeNumber += generateRuntimeAnnotations(annotations);
+ }
+ }
+ }
// update the number of attributes
if (attributeOffset + 2 >= this.contents.length) {
resizeContents(2);
@@ -335,7 +664,7 @@ public class ClassFile
header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
header[constantPoolOffset] = (byte) constantPoolCount;
}
-
+
/**
* INTERNAL USE-ONLY
* This methods generate all the default abstract method infos that correpond to
@@ -352,37 +681,14 @@ public class ClassFile
}
}
- /**
- * INTERNAL USE-ONLY
- * This methods generates the bytes for the field binding passed like a parameter
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- */
- public void addFieldInfo(FieldBinding fieldBinding) {
- int attributeNumber = 0;
- // check that there is enough space to write all the bytes for the field info corresponding
- // to the @fieldBinding
- if (contentsOffset + 30 >= contents.length) {
- resizeContents(30);
- }
- // Generate two attribute: constantValueAttribute and SyntheticAttribute
- // Now we can generate all entries into the byte array
- // First the accessFlags
- int accessFlags = fieldBinding.getAccessFlags();
- contents[contentsOffset++] = (byte) (accessFlags >> 8);
- contents[contentsOffset++] = (byte) accessFlags;
- // Then the nameIndex
- int nameIndex = constantPool.literalIndex(fieldBinding.name);
- contents[contentsOffset++] = (byte) (nameIndex >> 8);
- contents[contentsOffset++] = (byte) nameIndex;
- // Then the descriptorIndex
- int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
- contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
- contents[contentsOffset++] = (byte) descriptorIndex;
- // leave some space for the number of attributes
- int fieldAttributeOffset = contentsOffset;
- contentsOffset += 2;
+ private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
+ int attributesNumber = 0;
// 4.7.2 only static constant fields get a ConstantAttribute
- if (fieldBinding.constant != Constant.NotAConstant){
+ // Generate the constantValueAttribute
+ if (fieldBinding.isConstantValue()){
+ if (contentsOffset + 8 >= contents.length) {
+ resizeContents(8);
+ }
// Now we generate the constant attribute corresponding to the fieldBinding
int constantValueNameIndex =
constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
@@ -393,12 +699,13 @@ public class ClassFile
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 2;
- attributeNumber++;
+ attributesNumber++;
// Need to add the constant_value_index
- switch (fieldBinding.constant.typeID()) {
+ Constant fieldConstant = fieldBinding.constant();
+ switch (fieldConstant.typeID()) {
case T_boolean :
int booleanValueIndex =
- constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+ constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
contents[contentsOffset++] = (byte) booleanValueIndex;
break;
@@ -407,32 +714,32 @@ public class ClassFile
case T_int :
case T_short :
int integerValueIndex =
- constantPool.literalIndex(fieldBinding.constant.intValue());
+ constantPool.literalIndex(fieldConstant.intValue());
contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
contents[contentsOffset++] = (byte) integerValueIndex;
break;
case T_float :
int floatValueIndex =
- constantPool.literalIndex(fieldBinding.constant.floatValue());
+ constantPool.literalIndex(fieldConstant.floatValue());
contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
contents[contentsOffset++] = (byte) floatValueIndex;
break;
case T_double :
int doubleValueIndex =
- constantPool.literalIndex(fieldBinding.constant.doubleValue());
+ constantPool.literalIndex(fieldConstant.doubleValue());
contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
contents[contentsOffset++] = (byte) doubleValueIndex;
break;
case T_long :
int longValueIndex =
- constantPool.literalIndex(fieldBinding.constant.longValue());
+ constantPool.literalIndex(fieldConstant.longValue());
contents[contentsOffset++] = (byte) (longValueIndex >> 8);
contents[contentsOffset++] = (byte) longValueIndex;
break;
- case T_String :
+ case T_JavaLangString :
int stringValueIndex =
constantPool.literalIndex(
- ((StringConstant) fieldBinding.constant).stringValue());
+ ((StringConstant) fieldConstant).stringValue());
if (stringValueIndex == -1) {
if (!creatingProblemType) {
// report an error and abort: will lead to a problem type classfile creation
@@ -447,9 +754,7 @@ public class ClassFile
}
} else {
// already inside a problem type creation : no constant for this field
- contentsOffset = fieldAttributeOffset + 2;
- // +2 is necessary to keep the two byte space for the attribute number
- attributeNumber--;
+ contentsOffset = fieldAttributeOffset;
}
} else {
contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
@@ -457,7 +762,10 @@ public class ClassFile
}
}
}
- if (fieldBinding.isSynthetic()) {
+ if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
+ if (contentsOffset + 6 >= contents.length) {
+ resizeContents(6);
+ }
int syntheticAttributeNameIndex =
constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
@@ -467,9 +775,12 @@ public class ClassFile
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 0;
- attributeNumber++;
+ attributesNumber++;
}
if (fieldBinding.isDeprecated()) {
+ if (contentsOffset + 6 >= contents.length) {
+ resizeContents(6);
+ }
int deprecatedAttributeNameIndex =
constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
@@ -479,8 +790,75 @@ public class ClassFile
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 0;
contents[contentsOffset++] = 0;
- attributeNumber++;
+ attributesNumber++;
+ }
+ // add signature attribute
+ char[] genericSignature = fieldBinding.genericSignature();
+ if (genericSignature != null) {
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 8 >= contents.length) {
+ resizeContents(8);
+ }
+ int signatureAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+ contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+ // the length of a signature attribute is equals to 2
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ int signatureIndex =
+ constantPool.literalIndex(genericSignature);
+ contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureIndex;
+ attributesNumber++;
+ }
+ if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+ FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
+ if (fieldDeclaration != null) {
+ Annotation[] annotations = fieldDeclaration.annotations;
+ if (annotations != null) {
+ attributesNumber += generateRuntimeAnnotations(annotations);
+ }
+ }
+ }
+ return attributesNumber;
+ }
+ /**
+ * INTERNAL USE-ONLY
+ * This methods generates the bytes for the given field binding
+ * @param fieldBinding the given field binding
+ */
+ private void addFieldInfo(FieldBinding fieldBinding) {
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 8 >= contents.length) {
+ resizeContents(8);
}
+ // Now we can generate all entries into the byte array
+ // First the accessFlags
+ int accessFlags = fieldBinding.getAccessFlags();
+ if (targetJDK < ClassFileConstants.JDK1_5) {
+ // pre 1.5, synthetic was an attribute, not a modifier
+ accessFlags &= ~AccSynthetic;
+ }
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ // Then the nameIndex
+ int nameIndex = constantPool.literalIndex(fieldBinding.name);
+ contents[contentsOffset++] = (byte) (nameIndex >> 8);
+ contents[contentsOffset++] = (byte) nameIndex;
+ // Then the descriptorIndex
+ int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
+ contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[contentsOffset++] = (byte) descriptorIndex;
+ int fieldAttributeOffset = contentsOffset;
+ int attributeNumber = 0;
+ // leave some space for the number of attributes
+ contentsOffset += 2;
+ attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
contents[fieldAttributeOffset] = (byte) attributeNumber;
}
@@ -492,6 +870,13 @@ public class ClassFile
* - a field info for each defined field of that class
* - a field info for each synthetic field (e.g. this$0)
*/
+ /**
+ * INTERNAL USE-ONLY
+ * This methods generate all the fields infos for the receiver.
+ * This includes:
+ * - a field info for each defined field of that class
+ * - a field info for each synthetic field (e.g. this$0)
+ */
public void addFieldInfos() {
SourceTypeBinding currentBinding = referenceBinding;
FieldBinding[] syntheticFields = currentBinding.syntheticFields();
@@ -523,7 +908,7 @@ public class ClassFile
* have to be generated for the inner classes attributes.
* @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
*/
- public void addInnerClasses(ReferenceBinding refBinding) {
+ private void addInnerClasses(ReferenceBinding refBinding) {
// check first if that reference binding is there
for (int i = 0; i < numberOfInnerClasses; i++) {
if (innerClassesBindings[i] == refBinding)
@@ -540,6 +925,38 @@ public class ClassFile
}
innerClassesBindings[numberOfInnerClasses++] = refBinding;
}
+
+ private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
+ // always clear the strictfp/native/abstract bit for a problem method
+ generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(methodBinding);
+
+ // Code attribute
+ attributeNumber++;
+
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ StringBuffer buffer = new StringBuffer(25);
+ buffer.append("\t" + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+ String problemString = buffer.toString();
+
+ codeStream.init(this);
+ codeStream.preserveUnusedLocals = true;
+ codeStream.initializeMaxLocals(methodBinding);
+
+ // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+ codeStream.generateCodeAttributeForProblemMethod(problemString);
+
+ completeCodeAttributeForMissingAbstractProblemMethod(
+ methodBinding,
+ codeAttributeOffset,
+ compilationResult.lineSeparatorPositions,
+ problem.getSourceLineNumber());
+
+ completeMethodInfo(methodAttributeOffset, attributeNumber);
+ }
/**
* INTERNAL USE-ONLY
@@ -559,6 +976,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.resetForProblemClinit(this);
String problemString = "" ; //$NON-NLS-1$
+ int problemLine = 0;
if (problems != null) {
int max = problems.length;
StringBuffer buffer = new StringBuffer(25);
@@ -591,7 +1009,8 @@ public class ClassFile
.scope
.referenceCompilationUnit()
.compilationResult
- .lineSeparatorPositions);
+ .lineSeparatorPositions,
+ problemLine);
contents[attributeOffset++] = (byte) (attributeNumber >> 8);
contents[attributeOffset] = (byte) attributeNumber;
}
@@ -612,7 +1031,7 @@ public class ClassFile
// always clear the strictfp/native/abstract bit for a problem method
generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(methodBinding);
+ int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
// Code attribute
attributeNumber++;
@@ -620,6 +1039,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.reset(method, this);
String problemString = "" ; //$NON-NLS-1$
+ int problemLine = 0;
if (problems != null) {
int max = problems.length;
StringBuffer buffer = new StringBuffer(25);
@@ -652,7 +1072,8 @@ public class ClassFile
.scope
.referenceCompilationUnit()
.compilationResult
- .lineSeparatorPositions);
+ .lineSeparatorPositions,
+ problemLine);
completeMethodInfo(methodAttributeOffset, attributeNumber);
}
@@ -695,7 +1116,7 @@ public class ClassFile
// always clear the strictfp/native/abstract bit for a problem method
generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(methodBinding);
+ int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
// Code attribute
attributeNumber++;
@@ -704,6 +1125,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.reset(method, this);
String problemString = "" ; //$NON-NLS-1$
+ int problemLine = 0;
if (problems != null) {
int max = problems.length;
StringBuffer buffer = new StringBuffer(25);
@@ -740,7 +1162,8 @@ public class ClassFile
.scope
.referenceCompilationUnit()
.compilationResult
- .lineSeparatorPositions);
+ .lineSeparatorPositions,
+ problemLine);
completeMethodInfo(methodAttributeOffset, attributeNumber);
}
@@ -761,206 +1184,77 @@ public class ClassFile
int savedOffset) {
// we need to move back the contentsOffset to the value at the beginning of the method
contentsOffset = savedOffset;
- methodCount--; // we need to remove the method that causes the problem
- addProblemMethod(method, methodBinding, problems);
- }
-
- /**
- * INTERNAL USE-ONLY
- * Generate the byte for all the special method infos.
- * They are:
- * - synthetic access methods
- * - default abstract methods
- */
- public void addSpecialMethods() {
- // add all methods (default abstract methods and synthetic)
-
- // default abstract methods
- SourceTypeBinding currentBinding = referenceBinding;
- MethodBinding[] defaultAbstractMethods =
- currentBinding.getDefaultAbstractMethods();
- for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
- generateMethodInfoHeader(defaultAbstractMethods[i]);
- int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
- completeMethodInfo(methodAttributeOffset, attributeNumber);
- }
- // add synthetic methods infos
- SyntheticAccessMethodBinding[] syntheticAccessMethods =
- currentBinding.syntheticAccessMethods();
- if (syntheticAccessMethods != null) {
- for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
- SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
- switch (accessMethodBinding.accessType) {
- case SyntheticAccessMethodBinding.FieldReadAccess :
- // generate a method info to emulate an reading access to
- // a non-accessible field
- addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.FieldWriteAccess :
- // generate a method info to emulate an writing access to
- // a non-accessible field
- addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.MethodAccess :
- case SyntheticAccessMethodBinding.SuperMethodAccess :
- // generate a method info to emulate an access to a non-accessible method / super-method
- addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
- break;
- case SyntheticAccessMethodBinding.ConstructorAccess :
- // generate a method info to emulate an access to a non-accessible constructor
- addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
- }
- }
- }
- }
-
- /**
- * INTERNAL USE-ONLY
- * Generate the byte for problem method infos that correspond to missing abstract methods.
- * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
- *
- * @param methodDeclarations Array of all missing abstract methods
- */
- public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
- if (methodDeclarations != null) {
- for (int i = 0, max = methodDeclarations.length; i < max; i++) {
- MethodDeclaration methodDeclaration = methodDeclarations[i];
- MethodBinding methodBinding = methodDeclaration.binding;
- String readableName = new String(methodBinding.readableName());
- IProblem[] problems = compilationResult.problems;
- int problemsCount = compilationResult.problemCount;
- for (int j = 0; j < problemsCount; j++) {
- IProblem problem = problems[j];
- if (problem != null
- && problem.getID() == IProblem.AbstractMethodMustBeImplemented
- && problem.getMessage().indexOf(readableName) != -1) {
- // we found a match
- addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
- }
- }
- }
- }
- }
-
- private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
- // always clear the strictfp/native/abstract bit for a problem method
- generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
- int methodAttributeOffset = contentsOffset;
- int attributeNumber = generateMethodInfoAttribute(methodBinding);
-
- // Code attribute
- attributeNumber++;
-
- int codeAttributeOffset = contentsOffset;
- generateCodeAttributeHeader();
- StringBuffer buffer = new StringBuffer(25);
- buffer.append("\t" + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
- buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
- String problemString = buffer.toString();
- this.problemLine = problem.getSourceLineNumber();
-
- codeStream.init(this);
- codeStream.preserveUnusedLocals = true;
- codeStream.initializeMaxLocals(methodBinding);
-
- // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
- codeStream.generateCodeAttributeForProblemMethod(problemString);
-
- completeCodeAttributeForMissingAbstractProblemMethod(
- methodBinding,
- codeAttributeOffset,
- compilationResult.lineSeparatorPositions);
-
- completeMethodInfo(methodAttributeOffset, attributeNumber);
+ methodCount--; // we need to remove the method that causes the problem
+ addProblemMethod(method, methodBinding, problems);
}
/**
- *
+ * INTERNAL USE-ONLY
+ * Generate the byte for all the special method infos.
+ * They are:
+ * - synthetic access methods
+ * - default abstract methods
*/
- public void completeCodeAttributeForMissingAbstractProblemMethod(
- MethodBinding binding,
- int codeAttributeOffset,
- int[] startLineIndexes) {
- // reinitialize the localContents with the byte modified by the code stream
- this.contents = codeStream.bCodeStream;
- int localContentsOffset = codeStream.classFileOffset;
- // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
- int max_stack = codeStream.stackMax;
- this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
- this.contents[codeAttributeOffset + 7] = (byte) max_stack;
- int max_locals = codeStream.maxLocals;
- this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
- this.contents[codeAttributeOffset + 9] = (byte) max_locals;
- int code_length = codeStream.position;
- this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
- this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
- this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
- this.contents[codeAttributeOffset + 13] = (byte) code_length;
- // write the exception table
- if (localContentsOffset + 50 >= this.contents.length) {
- resizeContents(50);
- }
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- // debug attributes
- int codeAttributeAttributeOffset = localContentsOffset;
- int attributeNumber = 0; // leave two bytes for the attribute_length
- localContentsOffset += 2; // first we handle the linenumber attribute
+ public void addSpecialMethods() {
+
+ // add all methods (default abstract methods and synthetic)
- if (codeStream.generateLineNumberAttributes) {
- /* Create and add the line number attribute (used for debugging)
- * Build the pairs of:
- * (bytecodePC lineNumber)
- * according to the table of start line indexes and the pcToSourceMap table
- * contained into the codestream
- */
- int lineNumberNameIndex =
- constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
- this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
- this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 6;
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 1;
- if (problemLine == 0) {
- problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
- }
- // first entry at pc = 0
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
- this.contents[localContentsOffset++] = (byte) problemLine;
- // now we change the size of the line number attribute
- attributeNumber++;
+ // default abstract methods
+ generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);
+
+ MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods();
+ for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+ generateMethodInfoHeader(defaultAbstractMethods[i]);
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+ completeMethodInfo(methodAttributeOffset, attributeNumber);
}
-
- // then we do the local variable attribute
- // update the number of attributes// ensure first that there is enough space available inside the localContents array
- if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
- resizeContents(2);
+ // add synthetic methods infos
+ SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
+ if (syntheticMethods != null) {
+ for (int i = 0, max = syntheticMethods.length; i < max; i++) {
+ SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
+ switch (syntheticMethod.kind) {
+ case SyntheticMethodBinding.FieldReadAccess :
+ // generate a method info to emulate an reading access to
+ // a non-accessible field
+ addSyntheticFieldReadAccessMethod(syntheticMethod);
+ break;
+ case SyntheticMethodBinding.FieldWriteAccess :
+ // generate a method info to emulate an writing access to
+ // a non-accessible field
+ addSyntheticFieldWriteAccessMethod(syntheticMethod);
+ break;
+ case SyntheticMethodBinding.MethodAccess :
+ case SyntheticMethodBinding.SuperMethodAccess :
+ case SyntheticMethodBinding.BridgeMethod :
+ // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
+ addSyntheticMethodAccessMethod(syntheticMethod);
+ break;
+ case SyntheticMethodBinding.ConstructorAccess :
+ // generate a method info to emulate an access to a non-accessible constructor
+ addSyntheticConstructorAccessMethod(syntheticMethod);
+ break;
+ case SyntheticMethodBinding.EnumValues :
+ // generate a method info to define #values()
+ addSyntheticEnumValuesMethod(syntheticMethod);
+ break;
+ case SyntheticMethodBinding.EnumValueOf :
+ // generate a method info to define #valueOf(String)
+ addSyntheticEnumValueOfMethod(syntheticMethod);
+ break;
+ }
+ }
}
- this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
- this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
- // update the attribute length
- int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
- this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
- this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
- this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
- this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
- contentsOffset = localContentsOffset;
}
-
+
/**
* INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private constructor.
+ * Generate the bytes for a synthetic method that provides an access to a private constructor.
*
* @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
*/
- public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
generateMethodInfoHeader(methodBinding);
// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
contents[contentsOffset++] = 0;
@@ -970,7 +1264,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.init(this);
codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(
+ completeCodeAttributeForSyntheticMethod(
methodBinding,
codeAttributeOffset,
((SourceTypeBinding) methodBinding.declaringClass)
@@ -992,12 +1286,88 @@ public class ClassFile
/**
* INTERNAL USE-ONLY
+ * Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+ public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
+
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 1 attribute: the code attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 1;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
+ completeCodeAttributeForSyntheticMethod(
+ methodBinding,
+ codeAttributeOffset,
+ ((SourceTypeBinding) methodBinding.declaringClass)
+ .scope
+ .referenceCompilationUnit()
+ .compilationResult
+ .lineSeparatorPositions);
+// // add the synthetic attribute
+// int syntheticAttributeNameIndex =
+// constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+// contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+// contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+// // the length of a synthetic attribute is equals to 0
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+ public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
+
+ generateMethodInfoHeader(methodBinding);
+ // We know that we won't get more than 1 attribute: the code attribute
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 1;
+ // Code attribute
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ codeStream.init(this);
+ codeStream.generateSyntheticBodyForEnumValues(methodBinding);
+ completeCodeAttributeForSyntheticMethod(
+ methodBinding,
+ codeAttributeOffset,
+ ((SourceTypeBinding) methodBinding.declaringClass)
+ .scope
+ .referenceCompilationUnit()
+ .compilationResult
+ .lineSeparatorPositions);
+// // add the synthetic attribute
+// int syntheticAttributeNameIndex =
+// constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+// contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+// contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+// // the length of a synthetic attribute is equals to 0
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+// contents[contentsOffset++] = 0;
+
+ }
+
+ /**
+ * INTERNAL USE-ONLY
* Generate the byte for a problem method info that correspond to a synthetic method that
* generate an read access to a private field.
*
* @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
*/
- public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
generateMethodInfoHeader(methodBinding);
// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
contents[contentsOffset++] = 0;
@@ -1007,7 +1377,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.init(this);
codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(
+ completeCodeAttributeForSyntheticMethod(
methodBinding,
codeAttributeOffset,
((SourceTypeBinding) methodBinding.declaringClass)
@@ -1034,7 +1404,7 @@ public class ClassFile
*
* @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
*/
- public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
generateMethodInfoHeader(methodBinding);
// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
contents[contentsOffset++] = 0;
@@ -1044,7 +1414,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.init(this);
codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(
+ completeCodeAttributeForSyntheticMethod(
methodBinding,
codeAttributeOffset,
((SourceTypeBinding) methodBinding.declaringClass)
@@ -1066,12 +1436,11 @@ public class ClassFile
/**
* INTERNAL USE-ONLY
- * Generate the byte for a problem method info that correspond to a synthetic method that
- * generate an access to a private method.
+ * Generate the bytes for a synthetic method that provides access to a private method.
*
* @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
*/
- public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+ public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
generateMethodInfoHeader(methodBinding);
// We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
contents[contentsOffset++] = 0;
@@ -1081,7 +1450,7 @@ public class ClassFile
generateCodeAttributeHeader();
codeStream.init(this);
codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
- completeCodeAttributeForSyntheticAccessMethod(
+ completeCodeAttributeForSyntheticMethod(
methodBinding,
codeAttributeOffset,
((SourceTypeBinding) methodBinding.declaringClass)
@@ -1103,69 +1472,6 @@ public class ClassFile
/**
* INTERNAL USE-ONLY
- * Build all the directories and subdirectories corresponding to the packages names
- * into the directory specified in parameters.
- *
- * outputPath is formed like:
- * c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- * java\lang\String.class *
- *
- * @param outputPath java.lang.String
- * @param relativeFileName java.lang.String
- * @return java.lang.String
- */
- public static String buildAllDirectoriesInto(
- String outputPath,
- String relativeFileName)
- throws IOException {
- char fileSeparatorChar = File.separatorChar;
- String fileSeparator = File.separator;
- File f;
- // First we ensure that the outputPath exists
- outputPath = outputPath.replace('/', fileSeparatorChar);
- // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
- if (outputPath.endsWith(fileSeparator)) {
- outputPath = outputPath.substring(0, outputPath.length() - 1);
- }
- f = new File(outputPath);
- if (f.exists()) {
- if (!f.isDirectory()) {
- System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
- throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
- }
- } else {
- // we have to create that directory
- if (!f.mkdirs()) {
- System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
- throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
- }
- }
- StringBuffer outDir = new StringBuffer(outputPath);
- outDir.append(fileSeparator);
- StringTokenizer tokenizer =
- new StringTokenizer(relativeFileName, fileSeparator);
- String token = tokenizer.nextToken();
- while (tokenizer.hasMoreTokens()) {
- f = new File(outDir.append(token).append(fileSeparator).toString());
- if (f.exists()) {
- // The outDir already exists, so we proceed the next entry
- // System.out.println("outDir: " + outDir + " already exists.");
- } else {
- // Need to add the outDir
- if (!f.mkdir()) {
- System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
- throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
- }
- }
- token = tokenizer.nextToken();
- }
- // token contains the last one
- return outDir.append(token).toString();
- }
-
- /**
- * INTERNAL USE-ONLY
* That method completes the creation of the code attribute by setting
* - the attribute_length
* - max_stack
@@ -1204,7 +1510,7 @@ public class ClassFile
this.contents[codeAttributeOffset + 13] = (byte) code_length;
// write the exception table
- int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
int exSize = exceptionHandlersNumber * 8 + 2;
if (exSize + localContentsOffset >= this.contents.length) {
@@ -1214,31 +1520,33 @@ public class ClassFile
// on the attribute generation
this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
- for (int i = 0; i < exceptionHandlersNumber; i++) {
+ for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
ExceptionLabel exceptionHandler = exceptionHandlers[i];
- int start = exceptionHandler.start;
- this.contents[localContentsOffset++] = (byte) (start >> 8);
- this.contents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler.end;
- this.contents[localContentsOffset++] = (byte) (end >> 8);
- this.contents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler.position;
- this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
- this.contents[localContentsOffset++] = (byte) handlerPC;
- if (exceptionHandler.exceptionType == null) {
- // any exception handler
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- } else {
- int nameIndex;
- if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
- /* represents ClassNotFoundException, see class literal access*/
- nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ if (exceptionHandler != null) {
+ int start = exceptionHandler.start;
+ this.contents[localContentsOffset++] = (byte) (start >> 8);
+ this.contents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ this.contents[localContentsOffset++] = (byte) (end >> 8);
+ this.contents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ this.contents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
} else {
- nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ int nameIndex;
+ if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+ /* represents ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+ } else {
+ nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+ }
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
}
- this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
- this.contents[localContentsOffset++] = (byte) nameIndex;
}
}
// debug attributes
@@ -1300,8 +1608,14 @@ public class ClassFile
int numberOfEntries = 0;
int localVariableNameIndex =
constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
- if (localContentsOffset + 8 >= this.contents.length) {
- resizeContents(8);
+ final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+ int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
+ for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+ maxOfEntries += 10 * codeStream.locals[i].initializationCount;
+ }
+ // reserve enough space
+ if (localContentsOffset + maxOfEntries >= this.contents.length) {
+ resizeContents(maxOfEntries);
}
this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
@@ -1309,28 +1623,41 @@ public class ClassFile
// leave space for attribute_length and local_variable_table_length
int nameIndex;
int descriptorIndex;
- if (!codeStream.methodDeclaration.isStatic()) {
+ SourceTypeBinding declaringClassBinding = null;
+ if (!methodDeclarationIsStatic) {
numberOfEntries++;
- if (localContentsOffset + 10 >= this.contents.length) {
- resizeContents(10);
- }
this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
this.contents[localContentsOffset++] = 0;
this.contents[localContentsOffset++] = (byte) (code_length >> 8);
this.contents[localContentsOffset++] = (byte) code_length;
- nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ nameIndex = constantPool.literalIndex(ConstantPool.This);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
+ declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
descriptorIndex =
constantPool.literalIndex(
- codeStream.methodDeclaration.binding.declaringClass.signature());
+ declaringClassBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
this.contents[localContentsOffset++] = 0;
}
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+ // used to remember the local variable with a generic type
+ int genericLocalVariablesCounter = 0;
+ LocalVariableBinding[] genericLocalVariables = null;
+ int numberOfGenericEntries = 0;
+
+ for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
LocalVariableBinding localVariable = codeStream.locals[i];
+ final TypeBinding localVariableTypeBinding = localVariable.type;
+ boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+ if (localVariable.initializationCount != 0 && isParameterizedType) {
+ if (genericLocalVariables == null) {
+ // we cannot have more than max locals
+ genericLocalVariables = new LocalVariableBinding[max];
+ }
+ genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+ }
for (int j = 0; j < localVariable.initializationCount; j++) {
int startPC = localVariable.initializationPCs[j << 1];
int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1340,8 +1667,8 @@ public class ClassFile
Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
(ASTNode) localVariable.declaringScope.methodScope().referenceContext);
}
- if (localContentsOffset + 10 >= this.contents.length) {
- resizeContents(10);
+ if (isParameterizedType) {
+ numberOfGenericEntries++;
}
// now we can safely add the local entry
numberOfEntries++;
@@ -1353,7 +1680,7 @@ public class ClassFile
nameIndex = constantPool.literalIndex(localVariable.name);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
int resolvedPosition = localVariable.resolvedPosition;
@@ -1371,6 +1698,72 @@ public class ClassFile
this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
this.contents[localVariableTableOffset] = (byte) numberOfEntries;
attributeNumber++;
+
+ final boolean currentInstanceIsGeneric =
+ !methodDeclarationIsStatic
+ && declaringClassBinding != null
+ && declaringClassBinding.typeVariables != NoTypeVariables;
+ if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
+ // add the local variable type table attribute
+ numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
+ maxOfEntries = 8 + numberOfGenericEntries * 10;
+ // reserve enough space
+ if (localContentsOffset + maxOfEntries >= this.contents.length) {
+ resizeContents(maxOfEntries);
+ }
+ int localVariableTypeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+ this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+ value = numberOfGenericEntries * 10 + 2;
+ this.contents[localContentsOffset++] = (byte) (value >> 24);
+ this.contents[localContentsOffset++] = (byte) (value >> 16);
+ this.contents[localContentsOffset++] = (byte) (value >> 8);
+ this.contents[localContentsOffset++] = (byte) value;
+ this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+ this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+ if (currentInstanceIsGeneric) {
+ this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+ this.contents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(ConstantPool.This);
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+ this.contents[localContentsOffset++] = 0;
+ }
+
+ for (int i = 0; i < genericLocalVariablesCounter; i++) {
+ LocalVariableBinding localVariable = genericLocalVariables[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[(j << 1) + 1];
+ if (startPC != endPC) {
+ // only entries for non zero length
+ // now we can safely add the local entry
+ this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+ this.contents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ this.contents[localContentsOffset++] = (byte) (length >> 8);
+ this.contents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ this.contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ attributeNumber++;
+ }
}
// update the number of attributes
// ensure first that there is enough space available inside the localContents array
@@ -1429,7 +1822,7 @@ public class ClassFile
this.contents[codeAttributeOffset + 13] = (byte) code_length;
// write the exception table
- int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
int exSize = exceptionHandlersNumber * 8 + 2;
if (exSize + localContentsOffset >= this.contents.length) {
@@ -1439,31 +1832,33 @@ public class ClassFile
// on the attribute generation
this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
- for (int i = 0; i < exceptionHandlersNumber; i++) {
+ for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; i++) {
ExceptionLabel exceptionHandler = exceptionHandlers[i];
- int start = exceptionHandler.start;
- this.contents[localContentsOffset++] = (byte) (start >> 8);
- this.contents[localContentsOffset++] = (byte) start;
- int end = exceptionHandler.end;
- this.contents[localContentsOffset++] = (byte) (end >> 8);
- this.contents[localContentsOffset++] = (byte) end;
- int handlerPC = exceptionHandler.position;
- this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
- this.contents[localContentsOffset++] = (byte) handlerPC;
- if (exceptionHandler.exceptionType == null) {
- // any exception handler
- this.contents[localContentsOffset++] = 0;
- this.contents[localContentsOffset++] = 0;
- } else {
- int nameIndex;
- if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
- /* represents denote ClassNotFoundException, see class literal access*/
- nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ if (exceptionHandler != null) {
+ int start = exceptionHandler.start;
+ this.contents[localContentsOffset++] = (byte) (start >> 8);
+ this.contents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ this.contents[localContentsOffset++] = (byte) (end >> 8);
+ this.contents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ this.contents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
} else {
- nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ int nameIndex;
+ if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+ /* represents denote ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+ } else {
+ nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+ }
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
}
- this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
- this.contents[localContentsOffset++] = (byte) nameIndex;
}
}
// debug attributes
@@ -1534,11 +1929,27 @@ public class ClassFile
this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
localContentsOffset += 6;
+
// leave space for attribute_length and local_variable_table_length
int nameIndex;
int descriptorIndex;
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+
+ // used to remember the local variable with a generic type
+ int genericLocalVariablesCounter = 0;
+ LocalVariableBinding[] genericLocalVariables = null;
+ int numberOfGenericEntries = 0;
+
+ for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
LocalVariableBinding localVariable = codeStream.locals[i];
+ final TypeBinding localVariableTypeBinding = localVariable.type;
+ boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+ if (localVariable.initializationCount != 0 && isParameterizedType) {
+ if (genericLocalVariables == null) {
+ // we cannot have more than max locals
+ genericLocalVariables = new LocalVariableBinding[max];
+ }
+ genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+ }
for (int j = 0; j < localVariable.initializationCount; j++) {
int startPC = localVariable.initializationPCs[j << 1];
int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1553,6 +1964,9 @@ public class ClassFile
}
// now we can safely add the local entry
numberOfEntries++;
+ if (isParameterizedType) {
+ numberOfGenericEntries++;
+ }
this.contents[localContentsOffset++] = (byte) (startPC >> 8);
this.contents[localContentsOffset++] = (byte) startPC;
int length = endPC - startPC;
@@ -1561,7 +1975,7 @@ public class ClassFile
nameIndex = constantPool.literalIndex(localVariable.name);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
int resolvedPosition = localVariable.resolvedPosition;
@@ -1579,6 +1993,52 @@ public class ClassFile
this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
this.contents[localVariableTableOffset] = (byte) numberOfEntries;
attributeNumber++;
+
+ if (genericLocalVariablesCounter != 0) {
+ // add the local variable type table attribute
+ // reserve enough space
+ int maxOfEntries = 8 + numberOfGenericEntries * 10;
+
+ if (localContentsOffset + maxOfEntries >= this.contents.length) {
+ resizeContents(maxOfEntries);
+ }
+ int localVariableTypeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+ this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+ value = numberOfGenericEntries * 10 + 2;
+ this.contents[localContentsOffset++] = (byte) (value >> 24);
+ this.contents[localContentsOffset++] = (byte) (value >> 16);
+ this.contents[localContentsOffset++] = (byte) (value >> 8);
+ this.contents[localContentsOffset++] = (byte) value;
+ this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+ this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+ for (int i = 0; i < genericLocalVariablesCounter; i++) {
+ LocalVariableBinding localVariable = genericLocalVariables[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[(j << 1) + 1];
+ if (startPC != endPC) { // only entries for non zero length
+ // now we can safely add the local entry
+ this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+ this.contents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ this.contents[localContentsOffset++] = (byte) (length >> 8);
+ this.contents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ this.contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ attributeNumber++;
+ }
}
}
// update the number of attributes
@@ -1612,7 +2072,8 @@ public class ClassFile
*/
public void completeCodeAttributeForClinit(
int codeAttributeOffset,
- int[] startLineIndexes) {
+ int[] startLineIndexes,
+ int problemLine) {
// reinitialize the contents with the byte modified by the code stream
this.contents = codeStream.bCodeStream;
int localContentsOffset = codeStream.classFileOffset;
@@ -1711,6 +2172,85 @@ public class ClassFile
}
/**
+ *
+ */
+ public void completeCodeAttributeForMissingAbstractProblemMethod(
+ MethodBinding binding,
+ int codeAttributeOffset,
+ int[] startLineIndexes,
+ int problemLine) {
+ // reinitialize the localContents with the byte modified by the code stream
+ this.contents = codeStream.bCodeStream;
+ int localContentsOffset = codeStream.classFileOffset;
+ // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+ int max_stack = codeStream.stackMax;
+ this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+ int code_length = codeStream.position;
+ this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ this.contents[codeAttributeOffset + 13] = (byte) code_length;
+ // write the exception table
+ if (localContentsOffset + 50 >= this.contents.length) {
+ resizeContents(50);
+ }
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ // debug attributes
+ int codeAttributeAttributeOffset = localContentsOffset;
+ int attributeNumber = 0; // leave two bytes for the attribute_length
+ localContentsOffset += 2; // first we handle the linenumber attribute
+
+ if (codeStream.generateLineNumberAttributes) {
+ /* Create and add the line number attribute (used for debugging)
+ * Build the pairs of:
+ * (bytecodePC lineNumber)
+ * according to the table of start line indexes and the pcToSourceMap table
+ * contained into the codestream
+ */
+ int lineNumberNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 6;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 1;
+ if (problemLine == 0) {
+ problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+ }
+ // first entry at pc = 0
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+ this.contents[localContentsOffset++] = (byte) problemLine;
+ // now we change the size of the line number attribute
+ attributeNumber++;
+ }
+
+ // then we do the local variable attribute
+ // update the number of attributes// ensure first that there is enough space available inside the localContents array
+ if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+ resizeContents(2);
+ }
+ this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+ contentsOffset = localContentsOffset;
+ }
+
+ /**
* INTERNAL USE-ONLY
* That method completes the creation of the code attribute by setting
* - the attribute_length
@@ -1726,7 +2266,8 @@ public class ClassFile
AbstractMethodDeclaration method,
MethodBinding binding,
int codeAttributeOffset,
- int[] startLineIndexes) {
+ int[] startLineIndexes,
+ int problemLine) {
// reinitialize the localContents with the byte modified by the code stream
this.contents = codeStream.bCodeStream;
int localContentsOffset = codeStream.classFileOffset;
@@ -1803,7 +2344,10 @@ public class ClassFile
localContentsOffset += 6;
// leave space for attribute_length and local_variable_table_length
int descriptorIndex;
- if (!codeStream.methodDeclaration.isStatic()) {
+ int nameIndex;
+ SourceTypeBinding declaringClassBinding = null;
+ final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+ if (!methodDeclarationIsStatic) {
numberOfEntries++;
if (localContentsOffset + 10 >= this.contents.length) {
resizeContents(10);
@@ -1812,28 +2356,41 @@ public class ClassFile
this.contents[localContentsOffset++] = 0;
this.contents[localContentsOffset++] = (byte) (code_length >> 8);
this.contents[localContentsOffset++] = (byte) code_length;
- int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ nameIndex = constantPool.literalIndex(ConstantPool.This);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
+ declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
descriptorIndex =
- constantPool.literalIndex(
- codeStream.methodDeclaration.binding.declaringClass.signature());
+ constantPool.literalIndex(declaringClassBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
// the resolved position for this is always 0
this.contents[localContentsOffset++] = 0;
this.contents[localContentsOffset++] = 0;
}
+ // used to remember the local variable with a generic type
+ int genericLocalVariablesCounter = 0;
+ LocalVariableBinding[] genericLocalVariables = null;
+ int numberOfGenericEntries = 0;
+
if (binding.isConstructor()) {
ReferenceBinding declaringClass = binding.declaringClass;
if (declaringClass.isNestedType()) {
NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
argSize = methodDeclaringClass.enclosingInstancesSlotSize;
SyntheticArgumentBinding[] syntheticArguments;
- if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances())
- != null) {
+ if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
for (int i = 0, max = syntheticArguments.length; i < max; i++) {
LocalVariableBinding localVariable = syntheticArguments[i];
+ final TypeBinding localVariableTypeBinding = localVariable.type;
+ if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
+ if (genericLocalVariables == null) {
+ // we cannot have more than max locals
+ genericLocalVariables = new LocalVariableBinding[max];
+ }
+ genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+ numberOfGenericEntries++;
+ }
if (localContentsOffset + 10 >= this.contents.length) {
resizeContents(10);
}
@@ -1843,10 +2400,10 @@ public class ClassFile
this.contents[localContentsOffset++] = 0;
this.contents[localContentsOffset++] = (byte) (code_length >> 8);
this.contents[localContentsOffset++] = (byte) code_length;
- int nameIndex = constantPool.literalIndex(localVariable.name);
+ nameIndex = constantPool.literalIndex(localVariable.name);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
int resolvedPosition = localVariable.resolvedPosition;
@@ -1860,6 +2417,12 @@ public class ClassFile
} else {
argSize = binding.isStatic() ? 0 : 1;
}
+
+ int genericArgumentsCounter = 0;
+ int[] genericArgumentsNameIndexes = null;
+ int[] genericArgumentsResolvedPositions = null;
+ TypeBinding[] genericArgumentsTypeBindings = null;
+
if (method.binding != null) {
TypeBinding[] parameters = method.binding.parameters;
Argument[] arguments = method.arguments;
@@ -1875,13 +2438,24 @@ public class ClassFile
this.contents[localContentsOffset++] = 0;
this.contents[localContentsOffset++] = (byte) (code_length >> 8);
this.contents[localContentsOffset++] = (byte) code_length;
- int nameIndex = constantPool.literalIndex(arguments[i].name);
+ nameIndex = constantPool.literalIndex(arguments[i].name);
this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
this.contents[localContentsOffset++] = (byte) nameIndex;
+ int resolvedPosition = argSize;
+ if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
+ if (genericArgumentsCounter == 0) {
+ // we cannot have more than max locals
+ genericArgumentsNameIndexes = new int[max];
+ genericArgumentsResolvedPositions = new int[max];
+ genericArgumentsTypeBindings = new TypeBinding[max];
+ }
+ genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
+ genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
+ genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
+ }
descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
this.contents[localContentsOffset++] = (byte) descriptorIndex;
- int resolvedPosition = argSize;
if ((argumentBinding == BaseTypes.LongBinding)
|| (argumentBinding == BaseTypes.DoubleBinding))
argSize += 2;
@@ -1901,6 +2475,79 @@ public class ClassFile
this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
this.contents[localVariableTableOffset] = (byte) numberOfEntries;
attributeNumber++;
+
+ final boolean currentInstanceIsGeneric =
+ !methodDeclarationIsStatic
+ && declaringClassBinding != null
+ && declaringClassBinding.typeVariables != NoTypeVariables;
+ if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
+ // add the local variable type table attribute
+ numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
+ // reserve enough space
+ int maxOfEntries = 8 + numberOfEntries * 10;
+ if (localContentsOffset + maxOfEntries >= this.contents.length) {
+ resizeContents(maxOfEntries);
+ }
+ int localVariableTypeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+ this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+ value = numberOfEntries * 10 + 2;
+ this.contents[localContentsOffset++] = (byte) (value >> 24);
+ this.contents[localContentsOffset++] = (byte) (value >> 16);
+ this.contents[localContentsOffset++] = (byte) (value >> 8);
+ this.contents[localContentsOffset++] = (byte) value;
+ this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
+ this.contents[localContentsOffset++] = (byte) numberOfEntries;
+ if (currentInstanceIsGeneric) {
+ numberOfEntries++;
+ this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+ this.contents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(ConstantPool.This);
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+ this.contents[localContentsOffset++] = 0;
+ }
+
+ for (int i = 0; i < genericLocalVariablesCounter; i++) {
+ LocalVariableBinding localVariable = genericLocalVariables[i];
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+ this.contents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ this.contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ for (int i = 0; i < genericArgumentsCounter; i++) {
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = 0;
+ this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+ this.contents[localContentsOffset++] = (byte) code_length;
+ nameIndex = genericArgumentsNameIndexes[i];
+ this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
+ this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = genericArgumentsResolvedPositions[i];
+ this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ this.contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ attributeNumber++;
+ }
}
// update the number of attributes// ensure first that there is enough space available inside the localContents array
if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
@@ -1930,8 +2577,8 @@ public class ClassFile
* @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
* @param codeAttributeOffset int
*/
- public void completeCodeAttributeForSyntheticAccessMethod(
- SyntheticAccessMethodBinding binding,
+ public void completeCodeAttributeForSyntheticMethod(
+ SyntheticMethodBinding binding,
int codeAttributeOffset,
int[] startLineIndexes) {
// reinitialize the contents with the byte modified by the code stream
@@ -2005,8 +2652,23 @@ public class ClassFile
// leave space for attribute_length and local_variable_table_length
int nameIndex;
int descriptorIndex;
- for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+
+ // used to remember the local variable with a generic type
+ int genericLocalVariablesCounter = 0;
+ LocalVariableBinding[] genericLocalVariables = null;
+ int numberOfGenericEntries = 0;
+
+ for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
LocalVariableBinding localVariable = codeStream.locals[i];
+ final TypeBinding localVariableTypeBinding = localVariable.type;
+ boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+ if (localVariable.initializationCount != 0 && isParameterizedType) {
+ if (genericLocalVariables == null) {
+ // we cannot have more than max locals
+ genericLocalVariables = new LocalVariableBinding[max];
+ }
+ genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+ }
for (int j = 0; j < localVariable.initializationCount; j++) {
int startPC = localVariable.initializationPCs[j << 1];
int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -2021,6 +2683,9 @@ public class ClassFile
}
// now we can safely add the local entry
numberOfEntries++;
+ if (isParameterizedType) {
+ numberOfGenericEntries++;
+ }
contents[localContentsOffset++] = (byte) (startPC >> 8);
contents[localContentsOffset++] = (byte) startPC;
int length = endPC - startPC;
@@ -2029,7 +2694,7 @@ public class ClassFile
nameIndex = constantPool.literalIndex(localVariable.name);
contents[localContentsOffset++] = (byte) (nameIndex >> 8);
contents[localContentsOffset++] = (byte) nameIndex;
- descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
contents[localContentsOffset++] = (byte) descriptorIndex;
int resolvedPosition = localVariable.resolvedPosition;
@@ -2047,6 +2712,52 @@ public class ClassFile
contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
contents[localVariableTableOffset] = (byte) numberOfEntries;
attributeNumber++;
+
+ if (genericLocalVariablesCounter != 0) {
+ // add the local variable type table attribute
+ int maxOfEntries = 8 + numberOfGenericEntries * 10;
+ // reserve enough space
+ if (localContentsOffset + maxOfEntries >= this.contents.length) {
+ resizeContents(maxOfEntries);
+ }
+ int localVariableTypeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+ contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+ contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+ value = numberOfGenericEntries * 10 + 2;
+ contents[localContentsOffset++] = (byte) (value >> 24);
+ contents[localContentsOffset++] = (byte) (value >> 16);
+ contents[localContentsOffset++] = (byte) (value >> 8);
+ contents[localContentsOffset++] = (byte) value;
+ contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+ contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+
+ for (int i = 0; i < genericLocalVariablesCounter; i++) {
+ LocalVariableBinding localVariable = genericLocalVariables[i];
+ for (int j = 0; j < localVariable.initializationCount; j++) {
+ int startPC = localVariable.initializationPCs[j << 1];
+ int endPC = localVariable.initializationPCs[(j << 1) + 1];
+ if (startPC != endPC) { // only entries for non zero length
+ // now we can safely add the local entry
+ contents[localContentsOffset++] = (byte) (startPC >> 8);
+ contents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ contents[localContentsOffset++] = (byte) (length >> 8);
+ contents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ contents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+ contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ contents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ contents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ attributeNumber++;
+ }
}
// update the number of attributes
// ensure first that there is enough space available inside the contents array
@@ -2082,115 +2793,74 @@ public class ClassFile
/**
* INTERNAL USE-ONLY
- * Request the creation of a ClassFile compatible representation of a problematic type
+ * This methods returns a char[] representing the file name of the receiver
*
- * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
- * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+ * @return char[]
*/
- public static void createProblemType(
- TypeDeclaration typeDeclaration,
- CompilationResult unitResult) {
- SourceTypeBinding typeBinding = typeDeclaration.binding;
- ClassFile classFile = new ClassFile(typeBinding, null, true);
-
- // TODO (olivier) handle cases where a field cannot be generated (name too long)
- // TODO (olivier) handle too many methods
- // inner attributes
- if (typeBinding.isMemberType())
- classFile.recordEnclosingTypeAttributes(typeBinding);
+ public char[] fileName() {
+ return constantPool.UTF8Cache.returnKeyFor(1);
+ }
- // add its fields
- FieldBinding[] fields = typeBinding.fields;
- if ((fields != null) && (fields != NoFields)) {
- for (int i = 0, max = fields.length; i < max; i++) {
- if (fields[i].constant == null) {
- FieldReference.getConstantFor(fields[i], null, false, null);
- }
- }
- classFile.addFieldInfos();
- } else {
- // we have to set the number of fields to be equals to 0
- classFile.contents[classFile.contentsOffset++] = 0;
- classFile.contents[classFile.contentsOffset++] = 0;
- }
- // leave some space for the methodCount
- classFile.setForMethodInfos();
- // add its user defined methods
- MethodBinding[] methods = typeBinding.methods;
- AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
- int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
- int problemsLength;
- IProblem[] problems = unitResult.getErrors();
- if (problems == null) {
- problems = new IProblem[0];
- }
- IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
- System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
- if (methods != null) {
- if (typeBinding.isInterface()) {
- // we cannot create problem methods for an interface. So we have to generate a clinit
- // which should contain all the problem
- classFile.addProblemClinit(problemsCopy);
- for (int i = 0, max = methods.length; i < max; i++) {
- MethodBinding methodBinding;
- if ((methodBinding = methods[i]) != null) {
- // find the corresponding method declaration
- for (int j = 0; j < maxMethodDecl; j++) {
- if ((methodDeclarations[j] != null)
- && (methodDeclarations[j].binding == methods[i])) {
- if (!methodBinding.isConstructor()) {
- classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
- }
- break;
- }
- }
+ private void generateAnnotation(Annotation annotation, int attributeOffset) {
+ if (contentsOffset + 4 >= this.contents.length) {
+ resizeContents(4);
+ }
+ TypeBinding annotationTypeBinding = annotation.resolvedType;
+ if (annotationTypeBinding == null) {
+ this.contentsOffset = attributeOffset;
+ return;
+ }
+ final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
+ contents[contentsOffset++] = (byte) (typeIndex >> 8);
+ contents[contentsOffset++] = (byte) typeIndex;
+ if (annotation instanceof NormalAnnotation) {
+ NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
+ MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
+ if (memberValuePairs != null) {
+ final int memberValuePairsLength = memberValuePairs.length;
+ contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
+ contents[contentsOffset++] = (byte) memberValuePairsLength;
+ for (int i = 0; i < memberValuePairsLength; i++) {
+ MemberValuePair memberValuePair = memberValuePairs[i];
+ if (contentsOffset + 2 >= this.contents.length) {
+ resizeContents(2);
}
- }
- } else {
- for (int i = 0, max = methods.length; i < max; i++) {
- MethodBinding methodBinding;
- if ((methodBinding = methods[i]) != null) {
- // find the corresponding method declaration
- for (int j = 0; j < maxMethodDecl; j++) {
- if ((methodDeclarations[j] != null)
- && (methodDeclarations[j].binding == methods[i])) {
- AbstractMethodDeclaration methodDecl;
- if ((methodDecl = methodDeclarations[j]).isConstructor()) {
- classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
- } else {
- classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
- }
- break;
- }
- }
+ final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
+ contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+ contents[contentsOffset++] = (byte) elementNameIndex;
+ MethodBinding methodBinding = memberValuePair.binding;
+ if (methodBinding == null) {
+ contentsOffset = attributeOffset;
+ } else {
+ generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
}
}
+ } else {
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
}
- // add abstract methods
- classFile.addDefaultAbstractMethods();
- }
- // propagate generation of (problem) member types
- if (typeDeclaration.memberTypes != null) {
- for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
- TypeDeclaration memberType = typeDeclaration.memberTypes[i];
- if (memberType.binding != null) {
- classFile.recordNestedMemberAttribute(memberType.binding);
- ClassFile.createProblemType(memberType, unitResult);
- }
- }
- }
- classFile.addAttributes();
- unitResult.record(typeBinding.constantPoolName(), classFile);
- }
-
- /**
- * INTERNAL USE-ONLY
- * This methods returns a char[] representing the file name of the receiver
- *
- * @return char[]
- */
- public char[] fileName() {
- return constantPool.UTF8Cache.returnKeyFor(1);
+ } else if (annotation instanceof SingleMemberAnnotation) {
+ SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+ // this is a single member annotation (one member value)
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 1;
+ if (contentsOffset + 2 >= this.contents.length) {
+ resizeContents(2);
+ }
+ final int elementNameIndex = constantPool.literalIndex(VALUE);
+ contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+ contents[contentsOffset++] = (byte) elementNameIndex;
+ MethodBinding methodBinding = singleMemberAnnotation.singlePair.binding;
+ if (methodBinding == null) {
+ contentsOffset = attributeOffset;
+ } else {
+ generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
+ }
+ } else {
+ // this is a marker annotation (no member value pairs)
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ }
}
/**
@@ -2211,6 +2881,187 @@ public class ClassFile
contentsOffset += 12;
}
+ private void generateElementValue(
+ Expression defaultValue,
+ TypeBinding memberValuePairReturnType,
+ int attributeOffset) {
+ Constant constant = defaultValue.constant;
+ TypeBinding defaultValueBinding = defaultValue.resolvedType;
+ if (defaultValueBinding == null) {
+ contentsOffset = attributeOffset;
+ } else {
+ if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
+ // automatic wrapping
+ if (contentsOffset + 3 >= this.contents.length) {
+ resizeContents(3);
+ }
+ contents[contentsOffset++] = (byte) '[';
+ contents[contentsOffset++] = (byte) 0;
+ contents[contentsOffset++] = (byte) 1;
+ }
+ if (constant != null && constant != Constant.NotAConstant) {
+ generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
+ } else {
+ generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
+ }
+ }
+ }
+
+ /**
+ * @param attributeOffset
+ */
+ private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
+ if (contentsOffset + 3 >= this.contents.length) {
+ resizeContents(3);
+ }
+ switch (binding.id) {
+ case T_boolean :
+ contents[contentsOffset++] = (byte) 'Z';
+ int booleanValueIndex =
+ constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
+ contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+ contents[contentsOffset++] = (byte) booleanValueIndex;
+ break;
+ case T_byte :
+ contents[contentsOffset++] = (byte) 'B';
+ int integerValueIndex =
+ constantPool.literalIndex(constant.intValue());
+ contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+ contents[contentsOffset++] = (byte) integerValueIndex;
+ break;
+ case T_char :
+ contents[contentsOffset++] = (byte) 'C';
+ integerValueIndex =
+ constantPool.literalIndex(constant.intValue());
+ contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+ contents[contentsOffset++] = (byte) integerValueIndex;
+ break;
+ case T_int :
+ contents[contentsOffset++] = (byte) 'I';
+ integerValueIndex =
+ constantPool.literalIndex(constant.intValue());
+ contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+ contents[contentsOffset++] = (byte) integerValueIndex;
+ break;
+ case T_short :
+ contents[contentsOffset++] = (byte) 'S';
+ integerValueIndex =
+ constantPool.literalIndex(constant.intValue());
+ contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+ contents[contentsOffset++] = (byte) integerValueIndex;
+ break;
+ case T_float :
+ contents[contentsOffset++] = (byte) 'F';
+ int floatValueIndex =
+ constantPool.literalIndex(constant.floatValue());
+ contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+ contents[contentsOffset++] = (byte) floatValueIndex;
+ break;
+ case T_double :
+ contents[contentsOffset++] = (byte) 'D';
+ int doubleValueIndex =
+ constantPool.literalIndex(constant.doubleValue());
+ contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+ contents[contentsOffset++] = (byte) doubleValueIndex;
+ break;
+ case T_long :
+ contents[contentsOffset++] = (byte) 'J';
+ int longValueIndex =
+ constantPool.literalIndex(constant.longValue());
+ contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+ contents[contentsOffset++] = (byte) longValueIndex;
+ break;
+ case T_JavaLangString :
+ contents[contentsOffset++] = (byte) 's';
+ int stringValueIndex =
+ constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
+ if (stringValueIndex == -1) {
+ if (!creatingProblemType) {
+ // report an error and abort: will lead to a problem type classfile creation
+ TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+ typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
+ } else {
+ // already inside a problem type creation : no attribute
+ contentsOffset = attributeOffset;
+ }
+ } else {
+ contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+ contents[contentsOffset++] = (byte) stringValueIndex;
+ }
+ }
+ }
+
+ private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
+ if (defaultValueBinding != null) {
+ if (defaultValueBinding.isEnum()) {
+ if (contentsOffset + 5 >= this.contents.length) {
+ resizeContents(5);
+ }
+ contents[contentsOffset++] = (byte) 'e';
+ FieldBinding fieldBinding = null;
+ if (defaultValue instanceof QualifiedNameReference) {
+ QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
+ fieldBinding = (FieldBinding) nameReference.binding;
+ } else if (defaultValue instanceof SingleNameReference) {
+ SingleNameReference nameReference = (SingleNameReference) defaultValue;
+ fieldBinding = (FieldBinding) nameReference.binding;
+ } else {
+ contentsOffset = attributeOffset;
+ }
+ if (fieldBinding != null) {
+ final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
+ final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
+ contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
+ contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
+ contents[contentsOffset++] = (byte) enumConstantNameIndex;
+ }
+ } else if (defaultValueBinding.isAnnotationType()) {
+ if (contentsOffset + 1 >= this.contents.length) {
+ resizeContents(1);
+ }
+ contents[contentsOffset++] = (byte) '@';
+ generateAnnotation((Annotation) defaultValue, attributeOffset);
+ } else if (defaultValueBinding.isArrayType()) {
+ // array type
+ if (contentsOffset + 3 >= this.contents.length) {
+ resizeContents(3);
+ }
+ contents[contentsOffset++] = (byte) '[';
+ if (defaultValue instanceof ArrayInitializer) {
+ ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
+ int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
+ contents[contentsOffset++] = (byte) (arrayLength >> 8);
+ contents[contentsOffset++] = (byte) arrayLength;
+ for (int i = 0; i < arrayLength; i++) {
+ generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
+ }
+ } else {
+ contentsOffset = attributeOffset;
+ }
+ } else {
+ // class type
+ if (contentsOffset + 3 >= this.contents.length) {
+ resizeContents(3);
+ }
+ contents[contentsOffset++] = (byte) 'c';
+ if (defaultValue instanceof ClassLiteralAccess) {
+ ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
+ final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
+ contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
+ contents[contentsOffset++] = (byte) classInfoIndex;
+ } else {
+ contentsOffset = attributeOffset;
+ }
+ }
+ } else {
+ contentsOffset = attributeOffset;
+ }
+ }
+
+ public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+ return generateMethodInfoAttribute(methodBinding, false);
+ }
/**
* INTERNAL USE-ONLY
* That method generates the attributes of a code attribute.
@@ -2224,7 +3075,7 @@ public class ClassFile
* @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
* @return int
*/
- public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+ public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
// leave two bytes for the attribute_number
contentsOffset += 2;
// now we can handle all the attribute for that method info:
@@ -2258,7 +3109,7 @@ public class ClassFile
contents[contentsOffset++] = (byte) (length >> 8);
contents[contentsOffset++] = (byte) length;
for (int i = 0; i < length; i++) {
- int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+ int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName());
contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
contents[contentsOffset++] = (byte) exceptionIndex;
}
@@ -2300,9 +3151,72 @@ public class ClassFile
attributeNumber++;
}
+ // add signature attribute
+ char[] genericSignature = methodBinding.genericSignature();
+ if (genericSignature != null) {
+ // check that there is enough space to write all the bytes for the field info corresponding
+ // to the @fieldBinding
+ if (contentsOffset + 8 >= this.contents.length) {
+ resizeContents(8);
+ }
+ int signatureAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+ contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+ // the length of a signature attribute is equals to 2
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 0;
+ contents[contentsOffset++] = 2;
+ int signatureIndex =
+ constantPool.literalIndex(genericSignature);
+ contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+ contents[contentsOffset++] = (byte) signatureIndex;
+ attributeNumber++;
+ }
+ if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
+ AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
+ if (methodDeclaration != null) {
+ Annotation[] annotations = methodDeclaration.annotations;
+ if (annotations != null) {
+ attributeNumber += generateRuntimeAnnotations(annotations);
+ }
+ if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
+ Argument[] arguments = methodDeclaration.arguments;
+ if (arguments != null) {
+ attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
+ }
+ }
+ }
+ }
return attributeNumber;
}
+ public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
+ int attributesNumber = generateMethodInfoAttribute(methodBinding);
+ int attributeOffset = contentsOffset;
+ if ((declaration.modifiers & AccAnnotationDefault) != 0) {
+ // add an annotation default attribute
+ int annotationDefaultNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
+ contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
+ contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
+ int attributeLengthOffset = contentsOffset;
+ contentsOffset += 4;
+
+ generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
+ if (contentsOffset != attributeOffset) {
+ int attributeLength = contentsOffset - attributeLengthOffset - 4;
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+ contents[attributeLengthOffset++] = (byte) attributeLength;
+ attributesNumber++;
+ }
+ }
+ return attributesNumber;
+ }
+
/**
* INTERNAL USE-ONLY
* That method generates the header of a method info:
@@ -2368,11 +3282,11 @@ public class ClassFile
}
contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
- int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+ int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
contents[contentsOffset++] = (byte) (nameIndex >> 8);
contents[contentsOffset++] = (byte) nameIndex;
int descriptorIndex =
- constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+ constantPool.literalIndex(ConstantPool.ClinitSignature);
contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
contents[contentsOffset++] = (byte) descriptorIndex;
// We know that we won't get more than 1 attribute: the code attribute
@@ -2381,6 +3295,264 @@ public class ClassFile
}
/**
+ * INTERNAL USE-ONLY
+ * Generate the byte for problem method infos that correspond to missing abstract methods.
+ * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
+ *
+ * @param methodDeclarations Array of all missing abstract methods
+ */
+ public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
+ if (methodDeclarations != null) {
+ for (int i = 0, max = methodDeclarations.length; i < max; i++) {
+ MethodDeclaration methodDeclaration = methodDeclarations[i];
+ MethodBinding methodBinding = methodDeclaration.binding;
+ String readableName = new String(methodBinding.readableName());
+ IProblem[] problems = compilationResult.problems;
+ int problemsCount = compilationResult.problemCount;
+ for (int j = 0; j < problemsCount; j++) {
+ IProblem problem = problems[j];
+ if (problem != null
+ && problem.getID() == IProblem.AbstractMethodMustBeImplemented
+ && problem.getMessage().indexOf(readableName) != -1) {
+ // we found a match
+ addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param annotations
+ * @return the number of attributes created while dumping the annotations in the .class file
+ */
+ private int generateRuntimeAnnotations(final Annotation[] annotations) {
+ int attributesNumber = 0;
+ final int length = annotations.length;
+ int visibleAnnotationsCounter = 0;
+ int invisibleAnnotationsCounter = 0;
+
+ for (int i = 0; i < length; i++) {
+ Annotation annotation = annotations[i];
+ if (isRuntimeInvisible(annotation)) {
+ invisibleAnnotationsCounter++;
+ } else if (isRuntimeVisible(annotation)) {
+ visibleAnnotationsCounter++;
+ }
+ }
+
+ if (invisibleAnnotationsCounter != 0) {
+ int annotationAttributeOffset = contentsOffset;
+ if (contentsOffset + 10 >= contents.length) {
+ resizeContents(10);
+ }
+ int runtimeInvisibleAnnotationsAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
+ contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
+ int attributeLengthOffset = contentsOffset;
+ contentsOffset += 4; // leave space for the attribute length
+
+ int annotationsLengthOffset = contentsOffset;
+ contentsOffset += 2; // leave space for the annotations length
+
+ contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
+ contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
+
+ loop: for (int i = 0; i < length; i++) {
+ if (invisibleAnnotationsCounter == 0) break loop;
+ Annotation annotation = annotations[i];
+ if (isRuntimeInvisible(annotation)) {
+ generateAnnotation(annotation, annotationAttributeOffset);
+ invisibleAnnotationsCounter--;
+ if (this.contentsOffset == annotationAttributeOffset) {
+ break loop;
+ }
+ }
+ }
+ if (contentsOffset != annotationAttributeOffset) {
+ int attributeLength = contentsOffset - attributeLengthOffset - 4;
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+ contents[attributeLengthOffset++] = (byte) attributeLength;
+ attributesNumber++;
+ } else {
+ contentsOffset = annotationAttributeOffset;
+ }
+ }
+
+ if (visibleAnnotationsCounter != 0) {
+ int annotationAttributeOffset = contentsOffset;
+ if (contentsOffset + 10 >= contents.length) {
+ resizeContents(10);
+ }
+ int runtimeVisibleAnnotationsAttributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
+ contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
+ int attributeLengthOffset = contentsOffset;
+ contentsOffset += 4; // leave space for the attribute length
+
+ int annotationsLengthOffset = contentsOffset;
+ contentsOffset += 2; // leave space for the annotations length
+
+ contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
+ contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
+
+ loop: for (int i = 0; i < length; i++) {
+ if (visibleAnnotationsCounter == 0) break loop;
+ Annotation annotation = annotations[i];
+ if (isRuntimeVisible(annotation)) {
+ visibleAnnotationsCounter--;
+ generateAnnotation(annotation, annotationAttributeOffset);
+ if (this.contentsOffset == annotationAttributeOffset) {
+ break loop;
+ }
+ }
+ }
+ if (contentsOffset != annotationAttributeOffset) {
+ int attributeLength = contentsOffset - attributeLengthOffset - 4;
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+ contents[attributeLengthOffset++] = (byte) attributeLength;
+ attributesNumber++;
+ } else {
+ contentsOffset = annotationAttributeOffset;
+ }
+ }
+ return attributesNumber;
+ }
+
+ private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
+ final int argumentsLength = arguments.length;
+ final int VISIBLE_INDEX = 0;
+ final int INVISIBLE_INDEX = 1;
+ int invisibleParametersAnnotationsCounter = 0;
+ int visibleParametersAnnotationsCounter = 0;
+ int[][] annotationsCounters = new int[argumentsLength][2];
+ for (int i = 0; i < argumentsLength; i++) {
+ Argument argument = arguments[i];
+ Annotation[] annotations = argument.annotations;
+ if (annotations != null) {
+ for (int j = 0, max2 = annotations.length; j < max2; j++) {
+ Annotation annotation = annotations[j];
+ if (isRuntimeInvisible(annotation)) {
+ annotationsCounters[i][INVISIBLE_INDEX]++;
+ invisibleParametersAnnotationsCounter++;
+ } else if (isRuntimeVisible(annotation)) {
+ annotationsCounters[i][VISIBLE_INDEX]++;
+ visibleParametersAnnotationsCounter++;
+ }
+ }
+ }
+ }
+ int attributesNumber = 0;
+ int annotationAttributeOffset = contentsOffset;
+ if (invisibleParametersAnnotationsCounter != 0) {
+ if (contentsOffset + 7 >= contents.length) {
+ resizeContents(7);
+ }
+ int attributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
+ contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) attributeNameIndex;
+ int attributeLengthOffset = contentsOffset;
+ contentsOffset += 4; // leave space for the attribute length
+
+ contents[contentsOffset++] = (byte) argumentsLength;
+ invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
+ if (contentsOffset + 2 >= contents.length) {
+ resizeContents(2);
+ }
+ if (invisibleParametersAnnotationsCounter == 0) {
+ contents[contentsOffset++] = (byte) 0;
+ contents[contentsOffset++] = (byte) 0;
+ } else {
+ final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
+ contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
+ contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
+ if (numberOfInvisibleAnnotations != 0) {
+ Argument argument = arguments[i];
+ Annotation[] annotations = argument.annotations;
+ for (int j = 0, max = annotations.length; j < max; j++) {
+ Annotation annotation = annotations[j];
+ if (isRuntimeInvisible(annotation)) {
+ generateAnnotation(annotation, annotationAttributeOffset);
+ if (contentsOffset == annotationAttributeOffset) {
+ break invisibleLoop;
+ }
+ invisibleParametersAnnotationsCounter--;
+ }
+ }
+ }
+ }
+ }
+ if (contentsOffset != annotationAttributeOffset) {
+ int attributeLength = contentsOffset - attributeLengthOffset - 4;
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+ contents[attributeLengthOffset++] = (byte) attributeLength;
+ attributesNumber++;
+ } else {
+ contentsOffset = annotationAttributeOffset;
+ }
+ }
+ if (visibleParametersAnnotationsCounter != 0) {
+ if (contentsOffset + 7 >= contents.length) {
+ resizeContents(7);
+ }
+ int attributeNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
+ contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+ contents[contentsOffset++] = (byte) attributeNameIndex;
+ int attributeLengthOffset = contentsOffset;
+ contentsOffset += 4; // leave space for the attribute length
+
+ contents[contentsOffset++] = (byte) argumentsLength;
+ visibleLoop: for (int i = 0; i < argumentsLength; i++) {
+ if (contentsOffset + 2 >= contents.length) {
+ resizeContents(2);
+ }
+ if (visibleParametersAnnotationsCounter == 0) {
+ contents[contentsOffset++] = (byte) 0;
+ contents[contentsOffset++] = (byte) 0;
+ } else {
+ final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
+ contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
+ contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
+ if (numberOfVisibleAnnotations != 0) {
+ Argument argument = arguments[i];
+ Annotation[] annotations = argument.annotations;
+ for (int j = 0, max = annotations.length; j < max; j++) {
+ Annotation annotation = annotations[j];
+ if (isRuntimeVisible(annotation)) {
+ generateAnnotation(annotation, annotationAttributeOffset);
+ if (contentsOffset == annotationAttributeOffset) {
+ break visibleLoop;
+ }
+ visibleParametersAnnotationsCounter--;
+ }
+ }
+ }
+ }
+ }
+ if (contentsOffset != annotationAttributeOffset) {
+ int attributeLength = contentsOffset - attributeLengthOffset - 4;
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+ contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+ contents[attributeLengthOffset++] = (byte) attributeLength;
+ attributesNumber++;
+ } else {
+ contentsOffset = annotationAttributeOffset;
+ }
+ }
+ return attributesNumber;
+ }
+ /**
* EXTERNAL API
* Answer the actual bytes of the class file
*
@@ -2422,6 +3594,31 @@ public class ClassFile
}
}
+
+ private boolean isRuntimeInvisible(Annotation annotation) {
+ final TypeBinding annotationBinding = annotation.resolvedType;
+ if (annotationBinding == null) {
+ return false;
+ }
+ long metaTagBits = annotationBinding.getAnnotationTagBits();
+ if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+ return true; // by default the retention is CLASS
+
+ return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
+ }
+
+ private boolean isRuntimeVisible(Annotation annotation) {
+ final TypeBinding annotationBinding = annotation.resolvedType;
+ if (annotationBinding == null) {
+ return false;
+ }
+ long metaTagBits = annotationBinding.tagBits;
+ if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+ return false; // by default the retention is CLASS
+
+ return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
+ }
+
/**
* INTERNAL USE-ONLY
* Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
@@ -2520,39 +3717,6 @@ public class ClassFile
/**
* INTERNAL USE-ONLY
- * Search the line number corresponding to a specific position
- */
- public static final int searchLineNumber(
- int[] startLineIndexes,
- int position) {
- // this code is completely useless, but it is the same implementation than
- // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
- // if (startLineIndexes == null)
- // return 1;
- int length = startLineIndexes.length;
- if (length == 0)
- return 1;
- int g = 0, d = length - 1;
- int m = 0;
- while (g <= d) {
- m = (g + d) / 2;
- if (position < startLineIndexes[m]) {
- d = m - 1;
- } else
- if (position > startLineIndexes[m]) {
- g = m + 1;
- } else {
- return m + 1;
- }
- }
- if (position < startLineIndexes[m]) {
- return m + 1;
- }
- return m + 2;
- }
-
- /**
- * INTERNAL USE-ONLY
* This methods leaves the space for method counts recording.
*/
public void setForMethodInfos() {
@@ -2560,62 +3724,4 @@ public class ClassFile
methodCountOffset = contentsOffset;
contentsOffset += 2;
}
-
- /**
- * INTERNAL USE-ONLY
- * outputPath is formed like:
- * c:\temp\ the last character is a file separator
- * relativeFileName is formed like:
- * java\lang\String.class
- * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
- * @param outputPath the output directory
- * @param relativeFileName java.lang.String
- * @param contents byte[]
- *
- */
- public static void writeToDisk(
- boolean generatePackagesStructure,
- String outputPath,
- String relativeFileName,
- byte[] contents)
- throws IOException {
-
- BufferedOutputStream output = null;
- if (generatePackagesStructure) {
- output = new BufferedOutputStream(
- new FileOutputStream(
- new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
- } else {
- String fileName = null;
- char fileSeparatorChar = File.separatorChar;
- String fileSeparator = File.separator;
- // First we ensure that the outputPath exists
- outputPath = outputPath.replace('/', fileSeparatorChar);
- // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
- int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
- if (indexOfPackageSeparator == -1) {
- if (outputPath.endsWith(fileSeparator)) {
- fileName = outputPath + relativeFileName;
- } else {
- fileName = outputPath + fileSeparator + relativeFileName;
- }
- } else {
- int length = relativeFileName.length();
- if (outputPath.endsWith(fileSeparator)) {
- fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
- } else {
- fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
- }
- }
- output = new BufferedOutputStream(
- new FileOutputStream(
- new File(fileName)));
- }
- try {
- output.write(contents);
- } finally {
- output.flush();
- output.close();
- }
- }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/CompilationResult.java b/src/org/eclipse/jdt/internal/compiler/CompilationResult.java
index 684df0b..d6b7475 100644
--- a/src/org/eclipse/jdt/internal/compiler/CompilationResult.java
+++ b/src/org/eclipse/jdt/internal/compiler/CompilationResult.java
@@ -35,6 +35,7 @@ import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import java.util.*;
@@ -56,6 +57,7 @@ public class CompilationResult {
public int unitIndex, totalUnitsKnown;
public boolean hasBeenAccepted = false;
public char[] fileName;
+ public boolean hasInconsistentToplevelHierarchies = false; // record the fact some toplevel types have inconsistent hierarchies
public CompilationResult(
char[] fileName,
@@ -358,6 +360,10 @@ public class CompilationResult {
*/
public void record(char[] typeName, ClassFile classFile) {
+ SourceTypeBinding sourceType = classFile.referenceBinding;
+ if (!sourceType.isLocalType() && sourceType.isHierarchyInconsistent()) {
+ this.hasInconsistentToplevelHierarchies = true;
+ }
compiledTypes.put(typeName, classFile);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/Compiler.java b/src/org/eclipse/jdt/internal/compiler/Compiler.java
index 92c85dc..ba20e99 100644
--- a/src/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/src/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -180,7 +180,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
/**
* Add an additional binary type
*/
- public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+ public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
if (options.verbose) {
System.out.println(
Util.bind(
@@ -190,14 +190,14 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
// new Exception("TRACE BINARY").printStackTrace(System.out);
// System.out.println();
}
- lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+ lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
}
/**
* Add an additional compilation unit into the loop
* -> build compilation unit declarations, their bindings and record their results.
*/
- public void accept(ICompilationUnit sourceUnit) {
+ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
// Switch the current policy and compilation result for this unit to the requested one.
CompilationResult unitResult =
new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
@@ -220,7 +220,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
parsedUnit = parser.dietParse(sourceUnit, unitResult);
}
// initial type binding creation
- lookupEnvironment.buildTypeBindings(parsedUnit);
+ lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
this.addCompilationUnit(sourceUnit, parsedUnit);
// binding resolution
@@ -239,7 +239,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
/**
* Add additional source types
*/
- public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+ public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
problemReporter.abortDueToInternalError(
Util.bind(
"abort.againstSourceModel" , //$NON-NLS-1$
@@ -295,7 +295,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
}
// initial type binding creation
- lookupEnvironment.buildTypeBindings(parsedUnit);
+ lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
this.addCompilationUnit(sourceUnits[i], parsedUnit);
//} catch (AbortCompilationUnit e) {
// requestor.acceptResult(unitResult.tagAsAccepted());
@@ -340,11 +340,13 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
unitsToProcess[i] = null; // release reference to processed unit declaration
requestor.acceptResult(unit.compilationResult.tagAsAccepted());
if (options.verbose)
- System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
- new String[] {
- String.valueOf(i + 1),
- String.valueOf(totalUnits),
- new String(unit.getFileName())}));
+ System.out.println(
+ Util.bind(
+ "compilation.done", //$NON-NLS-1$
+ new String[] {
+ String.valueOf(i + 1),
+ String.valueOf(totalUnits),
+ new String(unit.getFileName())}));
}
} catch (AbortCompilation e) {
this.handleInternalException(e, unit);
@@ -546,7 +548,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
unit = unitsToProcess[0];
} else {
// initial type binding creation
- lookupEnvironment.buildTypeBindings(unit);
+ lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
// binding resolution
lookupEnvironment.completeTypeBindings();
diff --git a/src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java b/src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java
deleted file mode 100644
index 13e2858..0000000
--- a/src/org/eclipse/jdt/internal/compiler/ConfigurableOption.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler;
-
-/**
- * Generic option description, which can be modified independently from the
- * component it belongs to.
- *
- * @deprecated backport 1.0 internal functionality
- */
-
-import java.util.*;
-
-public class ConfigurableOption {
- private String componentName;
- private String optionName;
- private int id;
-
- private String category;
- private String name;
- private String description;
- private int currentValueIndex;
- private int defaultValueIndex;
- private String[] possibleValues;
-
- // special value for indicating that
- // the is the actual value
- public final static String[] NoDiscreteValue = {};
-/**
- * INTERNAL USE ONLY
- *
- * Initialize an instance of this class according to a specific locale
- *
- * @param loc java.util.Locale
- */
-public ConfigurableOption(
- String componentName,
- String optionName,
- Locale loc,
- int currentValueIndex) {
-
- this.componentName = componentName;
- this.optionName = optionName;
- this.currentValueIndex = currentValueIndex;
-
- ResourceBundle resource = null;
- try {
- String location = componentName.substring(0, componentName.lastIndexOf('.'));
- resource = ResourceBundle.getBundle(location + ".options", loc); //$NON-NLS-1$
- } catch (MissingResourceException e) {
- category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- description = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- possibleValues = new String[0];
- id = -1;
- }
- if (resource == null) return;
- try {
- id = Integer.parseInt(resource.getString(optionName + ".number")); //$NON-NLS-1$
- } catch (MissingResourceException e) {
- id = -1;
- } catch (NumberFormatException e) {
- id = -1;
- }
- try {
- category = resource.getString(optionName + ".category"); //$NON-NLS-1$
- } catch (MissingResourceException e) {
- category = "Missing ressources entries for" + componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- try {
- name = resource.getString(optionName + ".name"); //$NON-NLS-1$
- } catch (MissingResourceException e) {
- name = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- try {
- StringTokenizer tokenizer = new StringTokenizer(resource.getString(optionName + ".possibleValues"), "|"); //$NON-NLS-1$ //$NON-NLS-2$
- int numberOfValues = Integer.parseInt(tokenizer.nextToken());
- if(numberOfValues == -1){
- possibleValues = NoDiscreteValue;
- } else {
- possibleValues = new String[numberOfValues];
- int index = 0;
- while (tokenizer.hasMoreTokens()) {
- possibleValues[index] = tokenizer.nextToken();
- index++;
- }
- }
- } catch (MissingResourceException e) {
- possibleValues = new String[0];
- } catch (NoSuchElementException e) {
- possibleValues = new String[0];
- } catch (NumberFormatException e) {
- possibleValues = new String[0];
- }
- try {
- description = resource.getString(optionName + ".description"); //$NON-NLS-1$
- } catch (MissingResourceException e) {
- description = "Missing ressources entries for"+ componentName + " options"; //$NON-NLS-1$ //$NON-NLS-2$
- }
-}
-/**
- * Return a String that represents the localized category of the receiver.
- * @return java.lang.String
- */
-public String getCategory() {
- return category;
-}
-/**
- * Return a String that identifies the component owner (typically the qualified
- * type name of the class which it corresponds to).
- *
- * e.g. "org.eclipse.jdt.internal.compiler.api.Compiler"
- *
- * @return java.lang.String
- */
-public String getComponentName() {
- return componentName;
-}
-/**
- * Answer the index (in possibleValues array) of the current setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- *
- * @return int
- */
-public int getCurrentValueIndex() {
- return currentValueIndex;
-}
-/**
- * Answer the index (in possibleValues array) of the default setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- *
- * @return int
- */
-public int getDefaultValueIndex() {
- return defaultValueIndex;
-}
-/**
- * Return an String that represents the localized description of the receiver.
- *
- * @return java.lang.String
- */
-public String getDescription() {
- return description;
-}
-/**
- * Internal ID which allows the configurable component to identify this particular option.
- *
- * @return int
- */
-public int getID() {
- return id;
-}
-/**
- * Return a String that represents the localized name of the receiver.
- * @return java.lang.String
- */
-public String getName() {
- return name;
-}
-/**
- * Return an array of String that represents the localized possible values of the receiver.
- * @return java.lang.String[]
- */
-public String[] getPossibleValues() {
- return possibleValues;
-}
-/**
- * Change the index (in possibleValues array) of the current setting for this
- * particular option.
- *
- * In case the set of possibleValues is NoDiscreteValue, then this index is the
- * actual value (e.g. max line lenght set to 80).
- */
-public void setValueIndex(int newIndex) {
- currentValueIndex = newIndex;
-}
-public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("Configurable option for "); //$NON-NLS-1$
- buffer.append(this.componentName).append("\n"); //$NON-NLS-1$
- buffer.append("- category: ").append(this.category).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
- buffer.append("- name: ").append(this.name).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
- /* display current value */
- buffer.append("- current value: "); //$NON-NLS-1$
- if (possibleValues == NoDiscreteValue){
- buffer.append(this.currentValueIndex);
- } else {
- buffer.append(this.possibleValues[this.currentValueIndex]);
- }
- buffer.append("\n"); //$NON-NLS-1$
-
- /* display possible values */
- if (possibleValues != NoDiscreteValue){
- buffer.append("- possible values: ["); //$NON-NLS-1$
- for (int i = 0, max = possibleValues.length; i < max; i++) {
- if (i != 0)
- buffer.append(", "); //$NON-NLS-1$
- buffer.append(possibleValues[i]);
- }
- buffer.append("]\n"); //$NON-NLS-1$
- buffer.append("- curr. val. index: ").append(currentValueIndex).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- buffer.append("- description: ").append(description).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$
- return buffer.toString();
-}
- /**
- * Gets the optionName.
- * @return Returns a String
- */
- public String getOptionName() {
- return optionName;
- }
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/src/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 74ba90b..1457547 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
@@ -26,14 +27,14 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
public final static int Bit2 = 0x2; // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
public final static int Bit3 = 0x4; // return type (operator) | name reference kind (name ref) | implicit this (this ref)
public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
- public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit)
+ public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref)
public final static int Bit6 = 0x20; // depth (name ref, msg) | only value required (binary expression) | ignore need cast check (cast expression)
public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression)
public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator)
public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl)
public final static int Bit10= 0x200; // depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
public final static int Bit11 = 0x400; // depth (name ref, msg) | operator (operator) | is member type (type decl)
- public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator)
+ public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
public final static int Bit13 = 0x1000; // depth (name ref, msg)
public final static int Bit14 = 0x2000; // strictly assigned (reference lhs)
public final static int Bit15 = 0x4000; // is unnecessary cast (expression)
@@ -64,6 +65,22 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
public final static long Bit38L = 0x2000000000L;
public final static long Bit39L = 0x4000000000L;
public final static long Bit40L = 0x8000000000L;
+ public final static long Bit41L = 0x10000000000L;
+ public final static long Bit42L = 0x20000000000L;
+ public final static long Bit43L = 0x40000000000L;
+ public final static long Bit44L = 0x80000000000L;
+ public final static long Bit45L = 0x100000000000L;
+ public final static long Bit46L = 0x200000000000L;
+ public final static long Bit47L = 0x400000000000L;
+ public final static long Bit48L = 0x800000000000L;
+ public final static long Bit49L = 0x1000000000000L;
+ public final static long Bit50L = 0x2000000000000L;
+ public final static long Bit51L = 0x4000000000000L;
+ public final static long Bit52L = 0x8000000000000L;
+ public final static long Bit53L = 0x10000000000000L;
+ public final static long Bit54L = 0x20000000000000L;
+ public final static long Bit55L = 0x40000000000000L;
+ public final static long Bit56L = 0x80000000000000L;
public int bits = IsReachableMASK; // reachable by default
@@ -102,6 +119,7 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
public static final int IsAnonymousTypeMASK = Bit10; // used to test for anonymous
public static final int AnonymousAndLocalMask = IsAnonymousTypeMASK | IsLocalTypeMASK; // used to set anonymous marker
public static final int IsMemberTypeMASK = Bit11; // local member do not know it is local at parse time (need to look at binding)
+ public static final int HasAbstractMethods = Bit12; // used to promote abstract enums
// for type, method and field declarations
public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
@@ -132,15 +150,80 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
// for if statement
public static final int IsElseIfStatement = Bit30;
+ // for type reference
+ public static final int IsSuperType = Bit5;
+
+ // for variable argument
+ public static final int IsVarArgs = Bit15;
+
public ASTNode() {
super();
}
-
+ private static boolean checkInvocationArgument(BlockScope scope, Expression argument, TypeBinding parameterType, TypeBinding argumentType) {
+ argument.computeConversion(scope, parameterType, argumentType);
+
+ if (argumentType != NullBinding && parameterType.isWildcard() && ((WildcardBinding) parameterType).kind != Wildcard.SUPER)
+ return true; // unsafeWildcardInvocation
+ if (argumentType != parameterType && argumentType.isRawType())
+ if (parameterType.isBoundParameterizedType() || parameterType.isGenericType())
+ scope.problemReporter().unsafeRawConversion(argument, argumentType, parameterType);
+ return false;
+ }
+ public static void checkInvocationArguments(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) {
+ boolean unsafeWildcardInvocation = false;
+ TypeBinding[] params = method.parameters;
+ if (method.isVarargs()) {
+ // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2})
+ int lastIndex = params.length - 1;
+ for (int i = 0; i < lastIndex; i++)
+ if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+ unsafeWildcardInvocation = true;
+ int argLength = arguments.length;
+ if (lastIndex < argLength) { // vararg argument was provided
+ TypeBinding parameterType = params[lastIndex];
+ if (params.length != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions())
+ parameterType = ((ArrayBinding) parameterType).elementsType(); // single element was provided for vararg parameter
+ for (int i = lastIndex; i < argLength; i++)
+ if (checkInvocationArgument(scope, arguments[i], parameterType, argumentTypes[i]))
+ unsafeWildcardInvocation = true;
+ }
+
+ if (method.parameters.length == argumentTypes.length) { // 70056
+ int varargIndex = method.parameters.length - 1;
+ ArrayBinding varargType = (ArrayBinding) method.parameters[varargIndex];
+ TypeBinding lastArgType = argumentTypes[varargIndex];
+ if (lastArgType == NullBinding) {
+ if (!(varargType.leafComponentType().isBaseType() && varargType.dimensions() == 1))
+ scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+ } else if (varargType.dimensions <= lastArgType.dimensions()) {
+ int dimensions = lastArgType.dimensions();
+ if (lastArgType.leafComponentType().isBaseType())
+ dimensions--;
+ if (varargType.dimensions < dimensions)
+ scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+ else if (varargType.dimensions == dimensions && varargType.leafComponentType != lastArgType.leafComponentType())
+ scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite);
+ }
+ }
+ } else {
+ for (int i = 0, argLength = arguments.length; i < argLength; i++)
+ if (checkInvocationArgument(scope, arguments[i], params[i], argumentTypes[i]))
+ unsafeWildcardInvocation = true;
+ }
+ if (argsContainCast) {
+ CastExpression.checkNeedForArgumentCasts(scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite);
+ }
+ if (unsafeWildcardInvocation) {
+ scope.problemReporter().wildcardInvocation((ASTNode)invocationSite, receiverType, method, argumentTypes);
+ } else if (!receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) {
+ scope.problemReporter().unsafeRawInvocation((ASTNode)invocationSite, method);
+ }
+ }
public ASTNode concreteStatement() {
return this;
}
-
+
/* Answer true if the field use is considered deprecated.
* An access in the same compilation unit is allowed.
*/
@@ -173,7 +256,7 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
// ignore cases where method is used from within inside itself (e.g. direct recursions)
- method.modifiers |= AccPrivateUsed;
+ method.original().modifiers |= AccPrivateUsed;
}
if (!method.isViewedAsDeprecated()) return false;
@@ -210,9 +293,15 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
// ignore cases where type is used from within inside itself
- refType.modifiers |= AccPrivateUsed;
+ ((ReferenceBinding)refType.erasure()).modifiers |= AccPrivateUsed;
+ }
+
+ if (refType.hasRestrictedAccess()) {
+ AccessRestriction restriction = scope.environment().getAccessRestriction(type);
+ if (restriction != null) {
+ scope.problemReporter().forbiddenReference(type, this, restriction.getMessageTemplate());
+ }
}
-
if (!refType.isViewedAsDeprecated()) return false;
// inside same unit - no report
@@ -225,6 +314,15 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
public abstract StringBuffer print(int indent, StringBuffer output);
+ public static StringBuffer printAnnotations(Annotation[] annotations, StringBuffer output) {
+ int length = annotations.length;
+ for (int i = 0; i < length; i++) {
+ annotations[i].print(0, output);
+ output.append(" "); //$NON-NLS-1$
+ }
+ return output;
+ }
+
public static StringBuffer printIndent(int indent, StringBuffer output) {
for (int i = indent; i > 0; i--) output.append(" "); //$NON-NLS-1$
@@ -255,6 +353,68 @@ public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConst
output.append("abstract "); //$NON-NLS-1$
return output;
}
+
+ /**
+ * Resolve annotations, and check duplicates, answers combined tagBits
+ * for recognized standard annotations
+ */
+ public void resolveAnnotations(BlockScope scope, Annotation[] annotations, Binding recipient) {
+ if (recipient != null) {
+ switch (recipient.kind()) {
+ case Binding.PACKAGE :
+ // TODO (philippe) need support for package annotations
+ break;
+ case Binding.TYPE :
+ case Binding.GENERIC_TYPE :
+ case Binding.TYPE_PARAMETER :
+ ReferenceBinding type = (ReferenceBinding) recipient;
+ if ((type.tagBits & TagBits.AnnotationResolved) != 0) return;
+ type.tagBits |= TagBits.AnnotationResolved;
+ break;
+ case Binding.METHOD :
+ MethodBinding method = (MethodBinding) recipient;
+ if ((method.tagBits & TagBits.AnnotationResolved) != 0) return;
+ method.tagBits |= TagBits.AnnotationResolved;
+ break;
+ case Binding.FIELD :
+ FieldBinding field = (FieldBinding) recipient;
+ if ((field.tagBits & TagBits.AnnotationResolved) != 0) return;
+ field.tagBits |= TagBits.AnnotationResolved;
+ break;
+ case Binding.LOCAL :
+ LocalVariableBinding local = (LocalVariableBinding) recipient;
+ if ((local.tagBits & TagBits.AnnotationResolved) != 0) return;
+ local.tagBits |= TagBits.AnnotationResolved;
+ break;
+ }
+ }
+ if (annotations == null)
+ return;
+ int length = annotations.length;
+ TypeBinding[] annotationTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ Annotation annotation = annotations[i];
+ annotation.recipient = recipient;
+ annotationTypes[i] = annotation.resolveType(scope);
+ }
+ // check duplicate annotations
+ for (int i = 0; i < length; i++) {
+ TypeBinding annotationType = annotationTypes[i];
+ if (annotationType == null) continue;
+ boolean foundDuplicate = false;
+ for (int j = i+1; j < length; j++) {
+ if (annotationTypes[j] == annotationType) {
+ foundDuplicate = true;
+ annotationTypes[j] = null; // report it only once
+ scope.problemReporter().duplicateAnnotation(annotations[j]);
+ }
+ }
+ if (foundDuplicate) {
+ scope.problemReporter().duplicateAnnotation(annotations[i]);
+ }
+ }
+ }
+
public int sourceStart() {
return this.sourceStart;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index c25253e..985a97d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -32,6 +32,7 @@ public abstract class AbstractMethodDeclaration
public int declarationSourceEnd;
public int modifiers;
public int modifiersSourceStart;
+ public Annotation[] annotations;
public Argument[] arguments;
public TypeReference[] thrownExceptions;
public Statement[] statements;
@@ -83,7 +84,11 @@ public abstract class AbstractMethodDeclaration
int length = this.arguments.length;
for (int i = 0; i < length; i++) {
TypeBinding argType = this.binding == null ? null : this.binding.parameters[i];
- this.arguments[i].bind(this.scope, argType, used);
+ Argument argument = this.arguments[i];
+ argument.bind(this.scope, argType, used);
+ if (argument.annotations != null) {
+ this.binding.tagBits |= TagBits.HasParameterAnnotations;
+ }
}
}
}
@@ -187,7 +192,7 @@ public abstract class AbstractMethodDeclaration
}
}
- private void generateCode(ClassFile classFile) {
+ public void generateCode(ClassFile classFile) {
classFile.generateMethodInfoHeader(this.binding);
int methodAttributeOffset = classFile.contentsOffset;
@@ -258,6 +263,11 @@ public abstract class AbstractMethodDeclaration
return (this.modifiers & AccAbstract) != 0;
}
+ public boolean isAnnotationMethod() {
+
+ return false;
+ }
+
public boolean isClinit() {
return false;
@@ -278,6 +288,11 @@ public abstract class AbstractMethodDeclaration
return false;
}
+ public boolean isMethod() {
+
+ return false;
+ }
+
public boolean isNative() {
if (this.binding != null)
@@ -305,6 +320,20 @@ public abstract class AbstractMethodDeclaration
printIndent(tab, output);
printModifiers(this.modifiers, output);
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+
+ TypeParameter[] typeParams = typeParameters();
+ if (typeParams != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeParams[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeParams[max].print(0, output);
+ output.append('>');
+ }
+
printReturnType(0, output).append(this.selector).append('(');
if (this.arguments != null) {
for (int i = 0; i < this.arguments.length; i++) {
@@ -356,6 +385,7 @@ public abstract class AbstractMethodDeclaration
bindArguments();
bindThrownExceptions();
resolveJavadoc();
+ resolveAnnotations(scope, this.annotations, this.binding);
resolveStatements();
} catch (AbortMethod e) { // ========= abort on fatal error =============
this.ignoreFurtherInvestigation = true;
@@ -395,4 +425,8 @@ public abstract class AbstractMethodDeclaration
ClassScope classScope) {
// default implementation: subclass will define it
}
+
+ public TypeParameter[] typeParameters() {
+ return null;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index cce62fc..ec08039 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -15,6 +15,7 @@ import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
public abstract class AbstractVariableDeclaration extends Statement implements InvocationSite {
public int declarationEnd;
@@ -24,6 +25,7 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
public Expression initialization;
public int modifiers;
public int modifiersSourceStart;
+ public Annotation[] annotations;
public char[] name;
@@ -32,6 +34,27 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
return flowInfo;
}
+
+ public static final int FIELD = 1;
+ public static final int INITIALIZER = 2;
+ public static final int ENUM_CONSTANT = 3;
+ public static final int LOCAL_VARIABLE = 4;
+ public static final int PARAMETER = 5;
+ public static final int TYPE_PARAMETER = 6;
+
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return null;
+ }
+
+ /**
+ * Returns the constant kind of this variable declaration
+ */
+ public abstract int getKind();
+
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
*/
@@ -46,17 +69,29 @@ public abstract class AbstractVariableDeclaration extends Statement implements I
return false;
}
-
public StringBuffer printStatement(int indent, StringBuffer output) {
printIndent(indent, output);
printModifiers(this.modifiers, output);
- type.print(0, output).append(' ').append(this.name);
- if (initialization != null) {
- output.append(" = "); //$NON-NLS-1$
- initialization.printExpression(indent, output);
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+
+ if (type != null) {
+ type.print(0, output).append(' ');
+ }
+ output.append(this.name);
+ switch(getKind()) {
+ case ENUM_CONSTANT:
+ if (initialization != null) {
+ initialization.printExpression(indent, output);
+ }
+ return output.append(',');
+ default:
+ if (initialization != null) {
+ output.append(" = "); //$NON-NLS-1$
+ initialization.printExpression(indent, output);
+ }
+ return output.append(';');
}
- return output.append(';');
}
public void resolve(BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 2a47d4d..e631f12 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -15,15 +15,16 @@ import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
-public class AllocationExpression
- extends Expression
- implements InvocationSite {
+public class AllocationExpression extends Expression implements InvocationSite {
public TypeReference type;
public Expression[] arguments;
- public MethodBinding binding;
-
- MethodBinding syntheticAccessor;
+ public MethodBinding binding; // exact binding resulting from lookup
+ protected MethodBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
+ MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation
+ public TypeReference[] typeArguments;
+ public TypeBinding[] genericTypeArguments;
+ public FieldDeclaration enumConstant; // for enum constant initializations
public FlowInfo analyseCode(
BlockScope currentScope,
@@ -31,7 +32,7 @@ public class AllocationExpression
FlowInfo flowInfo) {
// check captured variables are initialized in current context (26134)
- checkCapturedLocalInitializationIfNecessary(this.binding.declaringClass, currentScope, flowInfo);
+ checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
// process arguments
if (arguments != null) {
@@ -74,7 +75,6 @@ public class AllocationExpression
currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
}
}
-
}
}
@@ -88,14 +88,20 @@ public class AllocationExpression
boolean valueRequired) {
int pc = codeStream.position;
- ReferenceBinding allocatedType = binding.declaringClass;
+ ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
codeStream.new_(allocatedType);
if (valueRequired) {
codeStream.dup();
}
// better highlight for allocation: display the type individually
- codeStream.recordPositionsFrom(pc, type.sourceStart);
+ if (this.type != null) { // null for enum constant body
+ codeStream.recordPositionsFrom(pc, this.type.sourceStart);
+ } else {
+ // push enum constant name and ordinal
+ codeStream.ldc(String.valueOf(enumConstant.name));
+ codeStream.generateInlinedValue(enumConstant.binding.id);
+ }
// handling innerclass instance allocation - enclosing instance arguments
if (allocatedType.isNestedType()) {
@@ -106,11 +112,7 @@ public class AllocationExpression
this);
}
// generate the arguments for constructor
- if (arguments != null) {
- for (int i = 0, count = arguments.length; i < count; i++) {
- arguments[i].generateCode(currentScope, codeStream, true);
- }
- }
+ generateArguments(binding, arguments, currentScope, codeStream);
// handling innerclass instance allocation - outer local arguments
if (allocatedType.isNestedType()) {
codeStream.generateSyntheticOuterArgumentValues(
@@ -120,20 +122,27 @@ public class AllocationExpression
}
// invoke constructor
if (syntheticAccessor == null) {
- codeStream.invokespecial(binding);
+ codeStream.invokespecial(this.codegenBinding);
} else {
// synthetic accessor got some extra arguments appended to its signature, which need values
for (int i = 0,
- max = syntheticAccessor.parameters.length - binding.parameters.length;
+ max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
i < max;
i++) {
codeStream.aconst_null();
}
codeStream.invokespecial(syntheticAccessor);
}
+ codeStream.generateImplicitConversion(this.implicitConversion);
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return this.genericTypeArguments;
+ }
+
public boolean isSuperAccess() {
return false;
@@ -154,18 +163,18 @@ public class AllocationExpression
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
if (!flowInfo.isReachable()) return;
- ReferenceBinding allocatedType;
+ ReferenceBinding allocatedTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
// perform some emulation work in case there is some and we are inside a local type only
- if ((allocatedType = binding.declaringClass).isNestedType()
+ if (allocatedTypeErasure.isNestedType()
&& currentScope.enclosingSourceType().isLocalType()) {
- if (allocatedType.isLocalType()) {
- ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, false);
+ if (allocatedTypeErasure.isLocalType()) {
+ ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false);
// request cascade of accesses
} else {
// locally propagate, since we already now the desired shape for sure
- currentScope.propagateInnerEmulation(allocatedType, false);
+ currentScope.propagateInnerEmulation(allocatedTypeErasure, false);
// request cascade of accesses
}
}
@@ -174,27 +183,42 @@ public class AllocationExpression
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
if (!flowInfo.isReachable()) return;
- if (binding.isPrivate()
- && (currentScope.enclosingSourceType() != binding.declaringClass)) {
-
- if (currentScope
- .environment()
- .options
- .isPrivateConstructorAccessChangingVisibility) {
- binding.tagForClearingPrivateModifier();
+
+ // if constructor from parameterized type got found, use the original constructor at codegen time
+ this.codegenBinding = this.binding.original();
+
+ if (this.codegenBinding.isPrivate()
+ && (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass)) {
+
+ if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility) {
+ this.codegenBinding.tagForClearingPrivateModifier();
// constructor will not be dumped as private, no emulation required thus
} else {
syntheticAccessor =
- ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ ((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+ currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
}
}
}
public StringBuffer printExpression(int indent, StringBuffer output) {
- output.append("new "); //$NON-NLS-1$
- type.printExpression(0, output);
+ if (this.type != null) { // type null for enum constant initializations
+ output.append("new "); //$NON-NLS-1$
+ }
+ if (typeArguments != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeArguments.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeArguments[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArguments[max].print(0, output);
+ output.append('>');
+ }
+ if (type != null) { // type null for enum constant initializations
+ type.printExpression(0, output);
+ }
output.append('(');
if (arguments != null) {
for (int i = 0; i < arguments.length; i++) {
@@ -209,9 +233,29 @@ public class AllocationExpression
// Propagate the type checking to the arguments, and check if the constructor is defined.
constant = NotAConstant;
- this.resolvedType = type.resolveType(scope);
+ if (this.type == null) {
+ // initialization of an enum constant
+ this.resolvedType = scope.enclosingSourceType();
+ } else {
+ this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
+ }
// will check for null after args are resolved
+ // resolve type arguments (for generic constructor call)
+ if (this.typeArguments != null) {
+ int length = this.typeArguments.length;
+ boolean argHasError = false; // typeChecks all arguments
+ this.genericTypeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+ argHasError = true;
+ }
+ }
+ if (argHasError) {
+ return null;
+ }
+ }
+
// buffering the arguments' types
boolean argsContainCast = false;
TypeBinding[] argumentTypes = NoParameters;
@@ -236,13 +280,13 @@ public class AllocationExpression
if (this.resolvedType == null)
return null;
- if (!this.resolvedType.canBeInstantiated()) {
+ // null type denotes fake allocation for enum constant inits
+ if (this.type != null && !this.resolvedType.canBeInstantiated()) {
scope.problemReporter().cannotInstantiate(type, this.resolvedType);
return this.resolvedType;
}
ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
- if (!(binding = scope.getConstructor(allocationType, argumentTypes, this))
- .isValidBinding()) {
+ if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) {
if (binding.declaringClass == null)
binding.declaringClass = allocationType;
scope.problemReporter().invalidConstructor(this, binding);
@@ -250,15 +294,9 @@ public class AllocationExpression
}
if (isMethodUseDeprecated(binding, scope))
scope.problemReporter().deprecatedMethod(binding, this);
+ if (this.arguments != null)
+ checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
- if (arguments != null) {
- for (int i = 0; i < arguments.length; i++) {
- arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
- }
- if (argsContainCast) {
- CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
- }
- }
return allocationType;
}
@@ -277,12 +315,17 @@ public class AllocationExpression
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
- int argumentsLength;
- type.traverse(visitor, scope);
- if (arguments != null) {
- argumentsLength = arguments.length;
- for (int i = 0; i < argumentsLength; i++)
- arguments[i].traverse(visitor, scope);
+ if (this.typeArguments != null) {
+ for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+ this.typeArguments[i].traverse(visitor, scope);
+ }
+ }
+ if (this.type != null) { // enum constant scenario
+ this.type.traverse(visitor, scope);
+ }
+ if (this.arguments != null) {
+ for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++)
+ this.arguments[i].traverse(visitor, scope);
}
}
visitor.endVisit(this, scope);
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java
new file mode 100644
index 0000000..fb31f38
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Annotation
+ */
+public abstract class Annotation extends Expression {
+
+ public TypeReference type;
+ public int declarationSourceEnd;
+ public Binding recipient;
+
+ final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
+
+ public static long getRetentionPolicy(char[] policyName) {
+ if (policyName == null || policyName.length == 0)
+ return 0;
+ switch(policyName[0]) {
+ case 'C' :
+ if (CharOperation.equals(policyName, TypeConstants.UPPER_CLASS))
+ return TagBits.AnnotationClassRetention;
+ break;
+ case 'S' :
+ if (CharOperation.equals(policyName, TypeConstants.UPPER_SOURCE))
+ return TagBits.AnnotationSourceRetention;
+ break;
+ case 'R' :
+ if (CharOperation.equals(policyName, TypeConstants.UPPER_RUNTIME))
+ return TagBits.AnnotationRuntimeRetention;
+ break;
+ }
+ return 0; // unknown
+ }
+
+ public static long getTargetElementType(char[] elementName) {
+ if (elementName == null || elementName.length == 0)
+ return 0;
+ switch(elementName[0]) {
+ case 'A' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_ANNOTATION_TYPE))
+ return TagBits.AnnotationForAnnotationType;
+ break;
+ case 'C' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_CONSTRUCTOR))
+ return TagBits.AnnotationForConstructor;
+ break;
+ case 'F' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_FIELD))
+ return TagBits.AnnotationForField;
+ break;
+ case 'L' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_LOCAL_VARIABLE))
+ return TagBits.AnnotationForLocalVariable;
+ break;
+ case 'M' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD))
+ return TagBits.AnnotationForMethod;
+ break;
+ case 'P' :
+ if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER))
+ return TagBits.AnnotationForParameter;
+ else if (CharOperation.equals(elementName, TypeConstants.UPPER_PACKAGE))
+ return TagBits.AnnotationForPackage;
+ break;
+ case 'T' :
+ if (CharOperation.equals(elementName, TypeConstants.TYPE))
+ return TagBits.AnnotationForType;
+ break;
+ }
+ return 0; // unknown
+ }
+
+ /**
+ * Compute the bit pattern for recognized standard annotations the compiler may need to act upon
+ */
+ private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationType, MemberValuePair valueAttribute) {
+ long tagBits = 0;
+ switch (annotationType.id) {
+ // retention annotation
+ case TypeIds.T_JavaLangAnnotationRetention :
+ if (valueAttribute != null) {
+ Expression expr = valueAttribute.value;
+ if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+ FieldBinding field = ((Reference)expr).fieldBinding();
+ if (field != null && field.declaringClass.id == T_JavaLangAnnotationRetentionPolicy) {
+ tagBits |= getRetentionPolicy(field.name);
+ }
+ }
+ }
+ break;
+ // target annotation
+ case TypeIds.T_JavaLangAnnotationTarget :
+ tagBits |= TagBits.AnnotationTarget; // target specified (could be empty)
+ if (valueAttribute != null) {
+ Expression expr = valueAttribute.value;
+ if (expr instanceof ArrayInitializer) {
+ ArrayInitializer initializer = (ArrayInitializer) expr;
+ final Expression[] expressions = initializer.expressions;
+ if (expressions != null) {
+ for (int i = 0, length = expressions.length; i < length; i++) {
+ Expression initExpr = expressions[i];
+ if ((initExpr.bits & Binding.VARIABLE) == Binding.FIELD) {
+ FieldBinding field = ((Reference) initExpr).fieldBinding();
+ if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+ long element = getTargetElementType(field.name);
+ if ((tagBits & element) != 0) {
+ scope.problemReporter().duplicateTargetInTargetAnnotation(annotationType, (NameReference)initExpr);
+ } else {
+ tagBits |= element;
+ }
+ }
+ }
+ }
+ }
+ } else if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+ FieldBinding field = ((Reference) expr).fieldBinding();
+ if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+ tagBits |= getTargetElementType(field.name);
+ }
+ }
+ }
+ break;
+ // marker annotations
+ case TypeIds.T_JavaLangDeprecated :
+ tagBits |= TagBits.AnnotationDeprecated;
+ break;
+ case TypeIds.T_JavaLangAnnotationDocumented :
+ tagBits |= TagBits.AnnotationDocumented;
+ break;
+ case TypeIds.T_JavaLangAnnotationInherited :
+ tagBits |= TagBits.AnnotationInherited;
+ break;
+ case TypeIds.T_JavaLangOverride :
+ tagBits |= TagBits.AnnotationOverride;
+ break;
+ case TypeIds.T_JavaLangSuppressWarnings :
+ tagBits |= TagBits.AnnotationSuppressWarnings;
+ break;
+ }
+ return tagBits;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ output.append('@');
+ this.type.printExpression(0, output);
+ return output;
+ }
+
+ public abstract MemberValuePair[] memberValuePairs();
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ this.constant = NotAConstant;
+
+ TypeBinding typeBinding = this.type.resolveType(scope);
+ if (typeBinding == null)
+ return null;
+ this.resolvedType = typeBinding;
+ // ensure type refers to an annotation type
+ if (!typeBinding.isAnnotationType()) {
+ scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type);
+ return null;
+ }
+
+ ReferenceBinding annotationType = (ReferenceBinding) this.resolvedType;
+ MethodBinding[] methods = annotationType.methods();
+ // clone valuePairs to keep track of unused ones
+ MemberValuePair[] valuePairs = memberValuePairs();
+ MemberValuePair valueAttribute = null; // remember the first 'value' pair
+ MemberValuePair[] usedValuePairs;
+ int pairsLength = valuePairs.length;
+ System.arraycopy(valuePairs, 0, usedValuePairs = new MemberValuePair[pairsLength], 0, pairsLength);
+
+ nextMember: for (int i = 0, requiredLength = methods.length; i < requiredLength; i++) {
+ MethodBinding method = methods[i];
+ char[] selector = method.selector;
+ boolean foundValue = false;
+ nextPair: for (int j = 0; j < pairsLength; j++) {
+ MemberValuePair valuePair = usedValuePairs[j];
+ if (valuePair == null) continue nextPair;
+ char[] memberName = valuePair.name;
+ if (CharOperation.equals(memberName, selector)) {
+ if (valueAttribute == null && CharOperation.equals(memberName, TypeConstants.VALUE)) {
+ valueAttribute = valuePair;
+ }
+ valuePair.binding = method;
+ usedValuePairs[j] = null; // consumed
+ foundValue = true;
+ boolean foundDuplicate = false;
+ for (int k = j+1; k < pairsLength; k++) {
+ if (CharOperation.equals(usedValuePairs[k].name, selector)) {
+ foundDuplicate = true;
+ scope.problemReporter().duplicateAnnotationValue(annotationType, usedValuePairs[k]);
+ usedValuePairs[k].binding = method;
+ usedValuePairs[k] = null;
+ }
+ }
+ if (foundDuplicate) {
+ scope.problemReporter().duplicateAnnotationValue(annotationType, valuePair);
+ continue nextMember;
+ }
+ valuePair.resolveTypeExpecting(scope, method.returnType);
+ }
+ }
+ if (!foundValue && (method.modifiers & AccAnnotationDefault) == 0) {
+ scope.problemReporter().missingValueForAnnotationMember(this, method.selector);
+ }
+ }
+ // check unused pairs
+ for (int i = 0; i < pairsLength; i++) {
+ if (usedValuePairs[i] != null) {
+ scope.problemReporter().undefinedAnnotationValue(annotationType, usedValuePairs[i]);
+ }
+ }
+ // recognize standard annotations ?
+ long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute);
+ if (this.recipient != null) {
+ if (tagBits != 0) {
+ // tag bits onto recipient
+ switch (this.recipient.kind()) {
+ case Binding.PACKAGE :
+ // TODO (philippe) need support for package annotations
+ break;
+ case Binding.TYPE :
+ case Binding.GENERIC_TYPE :
+ case Binding.TYPE_PARAMETER :
+ ((ReferenceBinding)this.recipient).tagBits |= tagBits;
+ break;
+ case Binding.METHOD :
+ ((MethodBinding)this.recipient).tagBits |= tagBits;
+ break;
+ case Binding.FIELD :
+ ((FieldBinding)this.recipient).tagBits |= tagBits;
+ break;
+ case Binding.LOCAL :
+ ((LocalVariableBinding)this.recipient).tagBits |= tagBits;
+ break;
+ }
+ }
+ // check (meta)target compatibility
+ checkTargetCompatibility: {
+ long metaTagBits = annotationType.getAnnotationTagBits();
+ if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) // does not specify any target restriction
+ break checkTargetCompatibility;
+
+ switch (recipient.kind()) {
+ case Binding.PACKAGE :
+ if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
+ break checkTargetCompatibility;
+ break;
+ case Binding.TYPE :
+ case Binding.GENERIC_TYPE :
+ if (((ReferenceBinding)this.recipient).isAnnotationType()) {
+ if ((metaTagBits & (TagBits.AnnotationForAnnotationType|TagBits.AnnotationForType)) != 0)
+ break checkTargetCompatibility;
+ } else if ((metaTagBits & TagBits.AnnotationForType) != 0)
+ break checkTargetCompatibility;
+ break;
+ case Binding.METHOD :
+ if (((MethodBinding)this.recipient).isConstructor()) {
+ if ((metaTagBits & TagBits.AnnotationForConstructor) != 0)
+ break checkTargetCompatibility;
+ } else if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
+ break checkTargetCompatibility;
+ break;
+ case Binding.FIELD :
+ if ((metaTagBits & TagBits.AnnotationForField) != 0)
+ break checkTargetCompatibility;
+ break;
+ case Binding.LOCAL :
+ if (((LocalVariableBinding)this.recipient).isArgument) {
+ if ((metaTagBits & TagBits.AnnotationForParameter) != 0)
+ break checkTargetCompatibility;
+ } else if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0)
+ break checkTargetCompatibility;
+ break;
+ }
+ scope.problemReporter().disallowedTargetForAnnotation(this);
+ }
+ }
+ return this.resolvedType;
+ }
+
+ public abstract void traverse(ASTVisitor visitor, BlockScope scope);
+ public abstract void traverse(ASTVisitor visitor, CompilationUnitScope scope);
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java
new file mode 100644
index 0000000..c7ef29f
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/AnnotationMethodDeclaration.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+
+public class AnnotationMethodDeclaration extends MethodDeclaration {
+
+ public Expression defaultValue;
+ public int extendedDimensions;
+
+ /**
+ * MethodDeclaration constructor comment.
+ */
+ public AnnotationMethodDeclaration(CompilationResult compilationResult) {
+ super(compilationResult);
+ }
+
+ public void generateCode(ClassFile classFile) {
+ classFile.generateMethodInfoHeader(this.binding);
+ int methodAttributeOffset = classFile.contentsOffset;
+ int attributeNumber = classFile.generateMethodInfoAttribute(this.binding, this);
+ classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
+ }
+
+ public boolean isAnnotationMethod() {
+
+ return true;
+ }
+
+ public boolean isMethod() {
+
+ return false;
+ }
+
+ public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+ // nothing to do
+ // annotation type member declaration don't have any body
+ }
+
+ public StringBuffer print(int tab, StringBuffer output) {
+
+ printIndent(tab, output);
+ printModifiers(this.modifiers, output);
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+
+ TypeParameter[] typeParams = typeParameters();
+ if (typeParams != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeParams[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeParams[max].print(0, output);
+ output.append('>');
+ }
+
+ printReturnType(0, output).append(this.selector).append('(');
+ if (this.arguments != null) {
+ for (int i = 0; i < this.arguments.length; i++) {
+ if (i > 0) output.append(", "); //$NON-NLS-1$
+ this.arguments[i].print(0, output);
+ }
+ }
+ output.append(')');
+ if (this.thrownExceptions != null) {
+ output.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < this.thrownExceptions.length; i++) {
+ if (i > 0) output.append(", "); //$NON-NLS-1$
+ this.thrownExceptions[i].print(0, output);
+ }
+ }
+
+ if (this.defaultValue != null) {
+ output.append(" default "); //$NON-NLS-1$
+ this.defaultValue.print(0, output);
+ }
+
+ printBody(tab + 1, output);
+ return output;
+ }
+
+ public void resolveStatements() {
+
+ super.resolveStatements();
+ if (this.arguments != null) {
+ scope.problemReporter().annotationMembersCannotHaveParameters(this);
+ }
+ if (this.typeParameters != null) {
+ scope.problemReporter().annotationMembersCannotHaveTypeParameters(this);
+ }
+ if (this.extendedDimensions != 0) {
+ scope.problemReporter().illegalExtendedDimensions(this);
+ }
+ if (this.binding == null) return;
+ TypeBinding returnTypeBinding = this.binding.returnType;
+ if (returnTypeBinding != null) {
+
+ // annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
+ checkAnnotationMethodType: {
+ TypeBinding leafReturnType = returnTypeBinding.leafComponentType();
+
+ switch (leafReturnType.erasure().id) {
+ case T_byte :
+ case T_short :
+ case T_char :
+ case T_int :
+ case T_long :
+ case T_float :
+ case T_double :
+ case T_boolean :
+ case T_JavaLangString :
+ case T_JavaLangClass :
+ if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+ break checkAnnotationMethodType;
+ }
+ if (leafReturnType.isEnum()) {
+ if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+ break checkAnnotationMethodType;
+ }
+ if (leafReturnType.isAnnotationType()) {
+ scope.classScope().detectAnnotationCycle(scope.enclosingSourceType(), leafReturnType, this.returnType);
+ if (returnTypeBinding.dimensions() <= 1) // only 1-dimensional array permitted
+ break checkAnnotationMethodType;
+ }
+ scope.problemReporter().invalidAnnotationMemberType(this);
+ }
+ if (this.defaultValue != null) {
+ MemberValuePair pair = new MemberValuePair(this.selector, this.sourceStart, this.sourceEnd, this.defaultValue);
+ pair.binding = this.binding;
+ pair.resolveTypeExpecting(scope, returnTypeBinding);
+ }
+ }
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ ClassScope classScope) {
+
+ if (visitor.visit(this, classScope)) {
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ if (this.returnType != null) {
+ this.returnType.traverse(visitor, scope);
+ }
+ if (this.defaultValue != null) {
+ this.defaultValue.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, classScope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Argument.java b/src/org/eclipse/jdt/internal/compiler/ast/Argument.java
index b6669ac..4a75e07 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -18,7 +18,7 @@ public class Argument extends LocalDeclaration {
// prefix for setter method (to recognize special hiding argument)
private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
-
+
public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
super(name, (int) (posNom >>> 32), (int) posNom);
@@ -31,11 +31,11 @@ public class Argument extends LocalDeclaration {
public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
if (this.type != null)
- this.type.resolvedType = typeBinding;
+ this.type.resolvedType = typeBinding; // TODO (philippe) no longer necessary as when binding got resolved, it was recorded already (SourceTypeBinding#resolveTypesFor(MethodBinding))
// record the resolved type into the type reference
int modifierFlag = this.modifiers;
- Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+ Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
scope.problemReporter().redefineArgument(this);
@@ -58,17 +58,29 @@ public class Argument extends LocalDeclaration {
scope.addLocalVariable(
this.binding =
new LocalVariableBinding(this, typeBinding, modifierFlag, true));
+ resolveAnnotations(scope, this.annotations, this.binding);
//true stand for argument instead of just local
- if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
- scope.problemReporter().deprecatedType(typeBinding, this.type);
this.binding.declaration = this;
this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
}
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ public int getKind() {
+ return PARAMETER;
+ }
+
+ public boolean isVarArgs() {
+ return (this.type.bits & IsVarArgs) != 0;
+ }
+
public StringBuffer print(int indent, StringBuffer output) {
printIndent(indent, output);
printModifiers(this.modifiers, output);
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+
if (type == null) {
output.append(" "); //$NON-NLS-1$
} else {
@@ -88,11 +100,23 @@ public class Argument extends LocalDeclaration {
// provide the scope with a side effect : insertion of a LOCAL
// that represents the argument. The type must be from JavaThrowable
- TypeBinding tb = type.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
- if (tb == null)
+ TypeBinding exceptionType = this.type.resolveType(scope, true /* check bounds*/);
+ if (exceptionType == null) return null;
+ if (exceptionType.isGenericType() || exceptionType.isParameterizedType()) {
+ scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this);
return null;
-
- Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+ }
+ if (exceptionType.isTypeVariable()) {
+ scope.problemReporter().invalidTypeVariableAsException(exceptionType, this);
+ return null;
+ }
+ TypeBinding throwable = scope.getJavaLangThrowable();
+ if (!exceptionType.isCompatibleWith(throwable)) {
+ scope.problemReporter().typeMismatchError(exceptionType, throwable, this);
+ return null;
+ }
+
+ Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
scope.problemReporter().redefineArgument(this);
@@ -101,10 +125,12 @@ public class Argument extends LocalDeclaration {
scope.problemReporter().localVariableHiding(this, existingVariable, false);
}
- binding = new LocalVariableBinding(this, tb, modifiers, false); // argument decl, but local var (where isArgument = false)
+ this.binding = new LocalVariableBinding(this, exceptionType, modifiers, false); // argument decl, but local var (where isArgument = false)
+ resolveAnnotations(scope, this.annotations, this.binding);
+
scope.addLocalVariable(binding);
- binding.constant = NotAConstant;
- return tb;
+ binding.setConstant(NotAConstant);
+ return exceptionType;
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index d9ab28d..d1862ff 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -73,7 +73,7 @@ public class ArrayAllocationExpression extends Expression {
// Generate a sequence of bytecodes corresponding to an array allocation
if (this.resolvedType.dimensions() == 1) {
// Mono-dimensional array
- codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
+ codeStream.newArray((ArrayBinding)this.resolvedType);
} else {
// Multi-dimensional array
codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
@@ -113,7 +113,7 @@ public class ArrayAllocationExpression extends Expression {
// only at the -end- like new int [4][][]. The parser allows new int[][4][]
// so this must be checked here......(this comes from a reduction to LL1 grammar)
- TypeBinding referenceType = type.resolveType(scope);
+ TypeBinding referenceType = type.resolveType(scope, true /* check bounds*/);
// will check for null after dimensions are checked
constant = Constant.NotAConstant;
@@ -124,12 +124,13 @@ public class ArrayAllocationExpression extends Expression {
// check the validity of the dimension syntax (and test for all null dimensions)
int explicitDimIndex = -1;
- for (int i = dimensions.length; --i >= 0;) {
+ loop: for (int i = dimensions.length; --i >= 0;) {
if (dimensions[i] != null) {
if (explicitDimIndex < 0) explicitDimIndex = i;
- } else if (explicitDimIndex> 0) {
+ } else if (explicitDimIndex > 0) {
// should not have an empty dimension before an non-empty one
- scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
+ scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex);
+ break loop;
}
}
@@ -139,6 +140,10 @@ public class ArrayAllocationExpression extends Expression {
if (explicitDimIndex < 0) {
scope.problemReporter().mustDefineDimensionsOrInitializer(this);
}
+ // allow new List>[5] - only check for generic array when no initializer, since also checked inside initializer resolution
+ if (referenceType != null && !referenceType.isReifiable()) {
+ scope.problemReporter().illegalGenericArray(referenceType, this);
+ }
} else if (explicitDimIndex >= 0) {
scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
}
@@ -148,7 +153,7 @@ public class ArrayAllocationExpression extends Expression {
if (dimensions[i] != null) {
TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
if (dimensionType != null) {
- dimensions[i].implicitWidening(IntBinding, dimensionType);
+ dimensions[i].computeConversion(scope, IntBinding, dimensionType);
}
}
}
@@ -158,7 +163,7 @@ public class ArrayAllocationExpression extends Expression {
if (dimensions.length > 255) {
scope.problemReporter().tooManyDimensions(this);
}
- this.resolvedType = scope.createArray(referenceType, dimensions.length);
+ this.resolvedType = scope.createArrayType(referenceType, dimensions.length);
// check the initializer
if (initializer != null) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/src/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
index b717047..9310cf7 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
@@ -47,7 +47,7 @@ public class ArrayInitializer extends Expression {
int pc = codeStream.position;
int expressionLength = (expressions == null) ? 0: expressions.length;
codeStream.generateInlinedValue(expressionLength);
- codeStream.newArray(currentScope, binding);
+ codeStream.newArray(binding);
if (expressions != null) {
// binding is an ArrayType, so I can just deal with the dimension
int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
@@ -101,7 +101,9 @@ public class ArrayInitializer extends Expression {
}
}
}
- if (!valueRequired) {
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(this.implicitConversion);
+ } else {
codeStream.pop();
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -133,12 +135,19 @@ public class ArrayInitializer extends Expression {
// this method is recursive... (the test on isArrayType is the stop case)
- constant = NotAConstant;
+ this.constant = NotAConstant;
+
+ // allow new List>[5]
+ TypeBinding leafComponentType = expectedTb.leafComponentType();
+ if (leafComponentType.isBoundParameterizedType() || leafComponentType.isGenericType() || leafComponentType.isTypeVariable()) {
+ scope.problemReporter().illegalGenericArray(leafComponentType, this);
+ }
+
if (expectedTb.isArrayType()) {
binding = (ArrayBinding) expectedTb;
if (expressions == null)
return binding;
- TypeBinding expectedElementsTb = binding.elementsType(scope);
+ TypeBinding expectedElementsTb = binding.elementsType();
if (expectedElementsTb.isBaseType()) {
for (int i = 0, length = expressions.length; i < length; i++) {
Expression expression = expressions[i];
@@ -150,12 +159,14 @@ public class ArrayInitializer extends Expression {
return null;
// Compile-time conversion required?
- if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
- expression.implicitWidening(expectedElementsTb, expressionTb);
- } else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
- expression.implicitWidening(expectedElementsTb, expressionTb);
+ if (expectedElementsTb != expressionTb) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(expectedElementsTb, expressionTb);
+ if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)
+ || BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)
+ || scope.isBoxingCompatibleWith(expressionTb, expectedElementsTb)) {
+ expression.computeConversion(scope, expectedElementsTb, expressionTb);
} else {
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
+ scope.problemReporter().typeMismatchError(expressionTb, expectedElementsTb, expression);
return null;
}
}
@@ -189,8 +200,8 @@ public class ArrayInitializer extends Expression {
}
}
if (leafElementType != null) {
- TypeBinding probableTb = scope.createArray(leafElementType, dim);
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
+ TypeBinding probableTb = scope.createArrayType(leafElementType, dim);
+ scope.problemReporter().typeMismatchError(probableTb, expectedTb, this);
}
return null;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index 701f3a6..6c6d1ad 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -10,8 +10,10 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
int dimensions;
@@ -22,32 +24,57 @@ public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
dimensions = dim ;
}
- public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
-
- super( sources , tb, poss);
- dimensions = dim ;
- }
-
public int dimensions() {
return dimensions;
}
+
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ int dim = this.dimensions;
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ int length = this.tokens.length;
+ char[][] qParamName = new char[length][];
+ System.arraycopy(this.tokens, 0, qParamName, 0, length-1);
+ qParamName[length-1] = CharOperation.concat(this.tokens[length-1], dimChars);
+ return qParamName;
+ }
- public TypeBinding getTypeBinding(Scope scope) {
+ protected TypeBinding getTypeBinding(Scope scope) {
if (this.resolvedType != null)
return this.resolvedType;
if (dimensions > 255) {
scope.problemReporter().tooManyDimensions(this);
}
- return scope.createArray(scope.getType(tokens), dimensions);
+ try {
+ TypeBinding leafComponentType = scope.getType(this.tokens, this.tokens.length);
+ return scope.createArrayType(leafComponentType, dimensions);
+ } catch (AbortCompilation e) {
+ e.updateContext(this, scope.referenceCompilationUnit().compilationResult);
+ throw e;
+ }
}
public StringBuffer printExpression(int indent, StringBuffer output){
super.printExpression(indent, output);
- for (int i = 0 ; i < dimensions ; i++) {
- output.append("[]"); //$NON-NLS-1$
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
}
return output;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
index 915b347..fc0bb69 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
@@ -51,10 +51,9 @@ public class ArrayReference extends Reference {
FlowContext flowContext,
FlowInfo flowInfo) {
- return position.analyseCode(
- currentScope,
- flowContext,
- receiver.analyseCode(currentScope, flowContext, flowInfo));
+ flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo);
+ receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+ return position.analyseCode(currentScope, flowContext, flowInfo);
}
public void generateAssignment(
@@ -123,21 +122,25 @@ public class ArrayReference extends Reference {
codeStream.dup2();
codeStream.arrayAt(this.resolvedType.id);
int operationTypeID;
- if ((operationTypeID = implicitConversion >> 4) == T_String) {
- codeStream.generateStringAppend(currentScope, null, expression);
- } else {
- // promote the array reference to the suitable operation type
- codeStream.generateImplicitConversion(implicitConversion);
- // generate the increment value (will by itself be promoted to the operation value)
- if (expression == IntLiteral.One) { // prefix operation
- codeStream.generateConstant(expression.constant, implicitConversion);
- } else {
- expression.generateCode(currentScope, codeStream, true);
- }
- // perform the operation
- codeStream.sendOperator(operator, operationTypeID);
- // cast the value back to the array reference type
- codeStream.generateImplicitConversion(assignmentImplicitConversion);
+ switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+ case T_JavaLangString :
+ case T_JavaLangObject :
+ case T_undefined :
+ codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+ break;
+ default :
+ // promote the array reference to the suitable operation type
+ codeStream.generateImplicitConversion(implicitConversion);
+ // generate the increment value (will by itself be promoted to the operation value)
+ if (expression == IntLiteral.One) { // prefix operation
+ codeStream.generateConstant(expression.constant, implicitConversion);
+ } else {
+ expression.generateCode(currentScope, codeStream, true);
+ }
+ // perform the operation
+ codeStream.sendOperator(operator, operationTypeID);
+ // cast the value back to the array reference type
+ codeStream.generateImplicitConversion(assignmentImplicitConversion);
}
codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
}
@@ -164,10 +167,11 @@ public class ArrayReference extends Reference {
codeStream.dup_x2();
}
}
+ codeStream.generateImplicitConversion(implicitConversion);
codeStream.generateConstant(
postIncrement.expression.constant,
implicitConversion);
- codeStream.sendOperator(postIncrement.operator, this.resolvedType.id);
+ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
codeStream.generateImplicitConversion(
postIncrement.assignmentImplicitConversion);
codeStream.arrayAtPut(this.resolvedType.id, false);
@@ -188,15 +192,16 @@ public class ArrayReference extends Reference {
}
TypeBinding arrayType = receiver.resolveType(scope);
if (arrayType != null) {
+ receiver.computeConversion(scope, arrayType, arrayType);
if (arrayType.isArrayType()) {
- this.resolvedType = ((ArrayBinding) arrayType).elementsType(scope);
+ this.resolvedType = ((ArrayBinding) arrayType).elementsType();
} else {
scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
}
}
TypeBinding positionType = position.resolveTypeExpecting(scope, IntBinding);
if (positionType != null) {
- position.implicitWidening(IntBinding, positionType);
+ position.computeConversion(scope, IntBinding, positionType);
}
return this.resolvedType;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index eec8865..66d9947 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -10,11 +10,16 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
public class ArrayTypeReference extends SingleTypeReference {
public int dimensions;
+ public int originalSourceEnd;
/**
* ArrayTypeReference constructor comment.
@@ -25,12 +30,7 @@ public class ArrayTypeReference extends SingleTypeReference {
public ArrayTypeReference(char[] source, int dimensions, long pos) {
super(source, pos);
- this.dimensions = dimensions ;
- }
-
- public ArrayTypeReference(char[] source, TypeBinding tb, int dimensions, long pos) {
-
- super(source, tb, pos);
+ this.originalSourceEnd = this.sourceEnd;
this.dimensions = dimensions ;
}
@@ -38,22 +38,42 @@ public class ArrayTypeReference extends SingleTypeReference {
return dimensions;
}
-
- public TypeBinding getTypeBinding(Scope scope) {
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ int dim = this.dimensions;
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ return new char[][]{ CharOperation.concat(token, dimChars) };
+ }
+ protected TypeBinding getTypeBinding(Scope scope) {
if (this.resolvedType != null) return this.resolvedType;
if (dimensions > 255) {
scope.problemReporter().tooManyDimensions(this);
}
- return scope.createArray(scope.getType(token), dimensions);
+ TypeBinding leafComponentType = scope.getType(token);
+ return scope.createArrayType(leafComponentType, dimensions);
}
public StringBuffer printExpression(int indent, StringBuffer output){
- super.printExpression(indent, output) ;
- for (int i= 0 ; i < dimensions ; i++) {
- output.append("[]"); //$NON-NLS-1$
+ super.printExpression(indent, output);
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
}
return output;
}
@@ -63,4 +83,10 @@ public class ArrayTypeReference extends SingleTypeReference {
visitor.visit(this, scope);
visitor.endVisit(this, scope);
}
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
index cf3093a..dedee1f 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -128,7 +129,7 @@ public class AssertStatement extends Statement {
case T_void :
scope.problemReporter().illegalVoidExpression(exceptionArgument);
default:
- id = T_Object;
+ id = T_JavaLangObject;
case T_boolean :
case T_byte :
case T_char :
@@ -137,7 +138,7 @@ public class AssertStatement extends Statement {
case T_float :
case T_int :
case T_long :
- case T_String :
+ case T_JavaLangString :
exceptionArgument.implicitConversion = (id << 4) + id;
}
}
@@ -168,7 +169,7 @@ public class AssertStatement extends Statement {
outerMostClass = (SourceTypeBinding) enclosing;
}
- this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(this, currentScope);
+ this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
// find and enable assertion support
TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
@@ -176,7 +177,7 @@ public class AssertStatement extends Statement {
for (int i = 0, max = methods.length; i < max; i++) {
AbstractMethodDeclaration method = methods[i];
if (method.isClinit()) {
- ((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding);
+ ((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding, currentScope.environment().options.sourceLevel < ClassFileConstants.JDK1_5);
break;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/src/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 5b86ade..e43c286 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -42,9 +42,25 @@ public class Assignment extends Expression {
// a field reference, a blank final field reference, a field of an enclosing instance or
// just a local variable.
- return ((Reference) lhs)
+ LocalVariableBinding local = this.lhs.localVariableBinding();
+ int nullStatus = this.expression.nullStatus(flowInfo);
+ if (local != null && nullStatus == FlowInfo.NULL) {
+ flowContext.recordUsingNullReference(currentScope, local, this.lhs, FlowInfo.NON_NULL, flowInfo);
+ }
+ flowInfo = ((Reference) lhs)
.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
.unconditionalInits();
+ if (local != null) {
+ switch(nullStatus) {
+ case FlowInfo.NULL :
+ flowInfo.markAsDefinitelyNull(local);
+ break;
+ case FlowInfo.NON_NULL :
+ flowInfo.markAsDefinitelyNonNull(local);
+ break;
+ }
+ }
+ return flowInfo;
}
void checkAssignmentEffect(BlockScope scope) {
@@ -56,6 +72,19 @@ public class Assignment extends Expression {
}
}
+ void checkAssignment(BlockScope scope, TypeBinding lhsType, TypeBinding rhsType) {
+
+ FieldBinding leftField = getLastField(this.lhs);
+ if (leftField != null && rhsType != NullBinding && lhsType.isWildcard() && ((WildcardBinding)lhsType).kind != Wildcard.SUPER) {
+ scope.problemReporter().wildcardAssignment(lhsType, rhsType, this.expression);
+ } else if (leftField != null && leftField.declaringClass != null /*length pseudo field*/&& leftField.declaringClass.isRawType()
+ && (rhsType.isParameterizedType() || rhsType.isGenericType())) {
+ scope.problemReporter().unsafeRawFieldAssignment(leftField, rhsType, this.lhs);
+ } else if (rhsType.needsUncheckedConversion(lhsType)) {
+ scope.problemReporter().unsafeRawConversion(this.expression, rhsType, lhsType);
+ }
+ }
+
public void generateCode(
BlockScope currentScope,
CodeStream codeStream,
@@ -89,6 +118,28 @@ public class Assignment extends Expression {
}
return null;
}
+ FieldBinding getLastField(Expression someExpression) {
+ if (someExpression instanceof SingleNameReference) {
+ if ((someExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+ return (FieldBinding) ((SingleNameReference)someExpression).binding;
+ }
+ } else if (someExpression instanceof FieldReference) {
+ return ((FieldReference)someExpression).binding;
+ } else if (someExpression instanceof QualifiedNameReference) {
+ QualifiedNameReference qName = (QualifiedNameReference) someExpression;
+ if (qName.otherBindings == null && ((someExpression.bits & RestrictiveFlagMASK) == Binding.FIELD)) {
+ return (FieldBinding)qName.binding;
+ } else {
+ return qName.otherBindings[qName.otherBindings.length - 1];
+ }
+ }
+ return null;
+ }
+
+ public int nullStatus(FlowInfo flowInfo) {
+ return this.expression.nullStatus(flowInfo);
+ }
+
public StringBuffer print(int indent, StringBuffer output) {
//no () when used as a statement
@@ -122,26 +173,30 @@ public class Assignment extends Expression {
scope.problemReporter().expressionShouldBeAVariable(this.lhs);
return null;
}
- this.resolvedType = lhs.resolveType(scope); // expressionType contains the assignment type (lhs Type)
+ TypeBinding lhsType = this.resolvedType = lhs.resolveType(scope);
+ expression.setExpectedType(lhsType); // needed in case of generic method invocation
TypeBinding rhsType = expression.resolveType(scope);
- if (this.resolvedType == null || rhsType == null) {
+ if (lhsType == null || rhsType == null) {
return null;
}
checkAssignmentEffect(scope);
-
+
// Compile-time conversion of base-types : implicit narrowing integer into byte/short/character
// may require to widen the rhs expression at runtime
- if ((expression.isConstantValueOfTypeAssignableToType(rhsType, this.resolvedType)
- || (this.resolvedType.isBaseType() && BaseTypeBinding.isWidening(this.resolvedType.id, rhsType.id)))
- || rhsType.isCompatibleWith(this.resolvedType)) {
- expression.implicitWidening(this.resolvedType, rhsType);
+ if (lhsType != rhsType) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(lhsType, rhsType);
+ if ((expression.isConstantValueOfTypeAssignableToType(rhsType, lhsType)
+ || (lhsType.isBaseType() && BaseTypeBinding.isWidening(lhsType.id, rhsType.id)))
+ || rhsType.isCompatibleWith(lhsType)) {
+ expression.computeConversion(scope, lhsType, rhsType);
+ checkAssignment(scope, lhsType, rhsType);
return this.resolvedType;
- }
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
- expression,
- rhsType,
- this.resolvedType);
- return this.resolvedType;
+ } else if (scope.isBoxingCompatibleWith(rhsType, lhsType)) {
+ expression.computeConversion(scope, lhsType, rhsType);
+ return this.resolvedType;
+ }
+ scope.problemReporter().typeMismatchError(rhsType, lhsType, expression);
+ return lhsType;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
@@ -151,13 +206,16 @@ public class Assignment extends Expression {
TypeBinding expectedType) {
TypeBinding type = super.resolveTypeExpecting(scope, expectedType);
+ if (type == null) return null;
+ TypeBinding lhsType = this.resolvedType;
+ TypeBinding rhsType = this.expression.resolvedType;
// signal possible accidental boolean assignment (instead of using '==' operator)
if (expectedType == BooleanBinding
- && this.lhs.resolvedType == BooleanBinding
+ && lhsType == BooleanBinding
&& (this.lhs.bits & IsStrictlyAssignedMASK) != 0) {
scope.problemReporter().possibleAccidentalBooleanAssignment(this);
}
-
+ checkAssignment(scope, lhsType, rhsType);
return type;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index b5804d0..d5a0b3e 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -96,8 +96,8 @@ public class BinaryExpression extends OperatorExpression {
switch ((bits & OperatorMASK) >> OperatorSHIFT) {
case PLUS :
switch (bits & ReturnTypeIDMASK) {
- case T_String :
- codeStream.generateStringAppend(currentScope, left, right);
+ case T_JavaLangString :
+ codeStream.generateStringConcatenationAppend(currentScope, left, right);
if (!valueRequired)
codeStream.pop();
break;
@@ -699,7 +699,7 @@ public class BinaryExpression extends OperatorExpression {
Label falseLabel,
boolean valueRequired) {
- int promotedTypeID = left.implicitConversion >> 4;
+ int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
// both sides got promoted in the same way
if (promotedTypeID == T_int) {
// 0 > x
@@ -813,7 +813,7 @@ public class BinaryExpression extends OperatorExpression {
Label falseLabel,
boolean valueRequired) {
- int promotedTypeID = left.implicitConversion >> 4;
+ int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
// both sides got promoted in the same way
if (promotedTypeID == T_int) {
// 0 >= x
@@ -927,7 +927,7 @@ public class BinaryExpression extends OperatorExpression {
Label falseLabel,
boolean valueRequired) {
- int promotedTypeID = left.implicitConversion >> 4;
+ int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
// both sides got promoted in the same way
if (promotedTypeID == T_int) {
// 0 < x
@@ -1037,7 +1037,7 @@ public class BinaryExpression extends OperatorExpression {
Label falseLabel,
boolean valueRequired) {
- int promotedTypeID = left.implicitConversion >> 4;
+ int promotedTypeID = (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
// both sides got promoted in the same way
if (promotedTypeID == T_int) {
// 0 <= x
@@ -1152,7 +1152,7 @@ public class BinaryExpression extends OperatorExpression {
boolean valueRequired) {
Constant condConst;
- if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
if (condConst.booleanValue() == true) {
// & x
@@ -1290,7 +1290,7 @@ public class BinaryExpression extends OperatorExpression {
boolean valueRequired) {
Constant condConst;
- if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
if (condConst.booleanValue() == true) {
// | x
@@ -1426,7 +1426,7 @@ public class BinaryExpression extends OperatorExpression {
boolean valueRequired) {
Constant condConst;
- if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
if (condConst.booleanValue() == true) {
// ^ x
@@ -1525,7 +1525,7 @@ public class BinaryExpression extends OperatorExpression {
codeStream.updateLastRecordedEndPC(codeStream.position);
}
- public void generateOptimizedStringBuffer(
+ public void generateOptimizedStringConcatenation(
BlockScope blockScope,
CodeStream codeStream,
int typeID) {
@@ -1536,30 +1536,30 @@ public class BinaryExpression extends OperatorExpression {
*/
if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
- && ((bits & ReturnTypeIDMASK) == T_String)) {
+ && ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
if (constant != NotAConstant) {
codeStream.generateConstant(constant, implicitConversion);
- codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
+ codeStream.invokeStringConcatenationAppendForType(implicitConversion & COMPILE_TYPE_MASK);
} else {
int pc = codeStream.position;
- left.generateOptimizedStringBuffer(
+ left.generateOptimizedStringConcatenation(
blockScope,
codeStream,
- left.implicitConversion & 0xF);
+ left.implicitConversion & COMPILE_TYPE_MASK);
codeStream.recordPositionsFrom(pc, left.sourceStart);
pc = codeStream.position;
- right.generateOptimizedStringBuffer(
+ right.generateOptimizedStringConcatenation(
blockScope,
codeStream,
- right.implicitConversion & 0xF);
+ right.implicitConversion & COMPILE_TYPE_MASK);
codeStream.recordPositionsFrom(pc, right.sourceStart);
}
} else {
- super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
+ super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID);
}
}
- public void generateOptimizedStringBufferCreation(
+ public void generateOptimizedStringConcatenationCreation(
BlockScope blockScope,
CodeStream codeStream,
int typeID) {
@@ -1570,29 +1570,29 @@ public class BinaryExpression extends OperatorExpression {
*/
if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
- && ((bits & ReturnTypeIDMASK) == T_String)) {
+ && ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
if (constant != NotAConstant) {
- codeStream.newStringBuffer(); // new: java.lang.StringBuffer
+ codeStream.newStringContatenation(); // new: java.lang.StringBuffer
codeStream.dup();
codeStream.ldc(constant.stringValue());
- codeStream.invokeStringBufferStringConstructor();
+ codeStream.invokeStringConcatenationStringConstructor();
// invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V
} else {
int pc = codeStream.position;
- left.generateOptimizedStringBufferCreation(
+ left.generateOptimizedStringConcatenationCreation(
blockScope,
codeStream,
- left.implicitConversion & 0xF);
+ left.implicitConversion & COMPILE_TYPE_MASK);
codeStream.recordPositionsFrom(pc, left.sourceStart);
pc = codeStream.position;
- right.generateOptimizedStringBuffer(
+ right.generateOptimizedStringConcatenation(
blockScope,
codeStream,
- right.implicitConversion & 0xF);
+ right.implicitConversion & COMPILE_TYPE_MASK);
codeStream.recordPositionsFrom(pc, right.sourceStart);
}
} else {
- super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
+ super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID);
}
}
@@ -1670,14 +1670,27 @@ public class BinaryExpression extends OperatorExpression {
constant = Constant.NotAConstant;
return null;
}
- int leftTypeId = leftType.id;
- int rightTypeId = rightType.id;
- if (leftTypeId > 15
- || rightTypeId > 15) { // must convert String + Object || Object + String
- if (leftTypeId == T_String) {
- rightTypeId = T_Object;
- } else if (rightTypeId == T_String) {
- leftTypeId = T_Object;
+
+ int leftTypeID = leftType.id;
+ int rightTypeID = rightType.id;
+
+ // autoboxing support
+ LookupEnvironment env = scope.environment();
+ boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+ if (use15specifics) {
+ if (!leftType.isBaseType() && rightTypeID != T_JavaLangString && rightTypeID != T_null) {
+ leftTypeID = env.computeBoxingType(leftType).id;
+ }
+ if (!rightType.isBaseType() && leftTypeID != T_JavaLangString && leftTypeID != T_null) {
+ rightTypeID = env.computeBoxingType(rightType).id;
+ }
+ }
+ if (leftTypeID > 15
+ || rightTypeID > 15) { // must convert String + Object || Object + String
+ if (leftTypeID == T_JavaLangString) {
+ rightTypeID = T_JavaLangObject;
+ } else if (rightTypeID == T_JavaLangString) {
+ leftTypeID = T_JavaLangObject;
} else {
constant = Constant.NotAConstant;
scope.problemReporter().invalidOperator(this, leftType, rightType);
@@ -1685,14 +1698,17 @@ public class BinaryExpression extends OperatorExpression {
}
}
if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
- if (leftTypeId == T_String
- && rightType.isArrayType()
- && ((ArrayBinding) rightType).elementsType(scope) == CharBinding) {
- scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
- } else if (rightTypeId == T_String
- && leftType.isArrayType()
- && ((ArrayBinding) leftType).elementsType(scope) == CharBinding) {
- scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
+ if (leftTypeID == T_JavaLangString) {
+ this.left.computeConversion(scope, leftType, leftType);
+ if (rightType.isArrayType() && ((ArrayBinding) rightType).elementsType() == CharBinding) {
+ scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
+ }
+ }
+ if (rightTypeID == T_JavaLangString) {
+ this.right.computeConversion(scope, rightType, rightType);
+ if (leftType.isArrayType() && ((ArrayBinding) leftType).elementsType() == CharBinding) {
+ scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
+ }
}
}
@@ -1704,10 +1720,10 @@ public class BinaryExpression extends OperatorExpression {
// Don't test for result = 0. If it is zero, some more work is done.
// On the one hand when it is not zero (correct code) we avoid doing the test
int operator = (bits & OperatorMASK) >> OperatorSHIFT;
- int operatorSignature = OperatorSignatures[operator][(leftTypeId << 4) + rightTypeId];
- left.implicitConversion = operatorSignature >>> 12;
- right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
+ int operatorSignature = OperatorSignatures[operator][(leftTypeID << 4) + rightTypeID];
+ left.computeConversion( scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), leftType);
+ right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), rightType);
bits |= operatorSignature & 0xF;
switch (operatorSignature & 0xF) { // record the current ReturnTypeID
// only switch on possible result type.....
@@ -1732,7 +1748,7 @@ public class BinaryExpression extends OperatorExpression {
case T_long :
this.resolvedType = LongBinding;
break;
- case T_String :
+ case T_JavaLangString :
this.resolvedType = scope.getJavaLangString();
break;
default : //error........
@@ -1743,10 +1759,10 @@ public class BinaryExpression extends OperatorExpression {
// check need for operand cast
if (leftIsCast || rightIsCast) {
- CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeId, leftIsCast, right, rightTypeId, rightIsCast);
+ CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeID, leftIsCast, right, rightTypeID, rightIsCast);
}
// compute the constant when valid
- computeConstant(scope, leftTypeId, rightTypeId);
+ computeConstant(scope, leftTypeID, rightTypeID);
return this.resolvedType;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
index 56380f7..ea3a9ae 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
@@ -20,6 +20,8 @@ public class CaseStatement extends Statement {
public Expression constantExpression;
public CaseLabel targetLabel;
+ boolean isEnumConstant;
+
public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
this.constantExpression = constantExpression;
this.sourceEnd = sourceEnd;
@@ -32,7 +34,7 @@ public class CaseStatement extends Statement {
FlowInfo flowInfo) {
if (constantExpression != null) {
- if (constantExpression.constant == NotAConstant) {
+ if (!this.isEnumConstant && constantExpression.constant == NotAConstant) {
currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
}
this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
@@ -73,9 +75,13 @@ public class CaseStatement extends Statement {
// no-op : should use resolveCase(...) instead.
}
+ /**
+ * Returns the constant intValue or ordinal for enum constants. If constant is NotAConstant, then answers Float.MIN_VALUE
+ * @see org.eclipse.jdt.internal.compiler.ast.Statement#resolveCase(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.ast.SwitchStatement)
+ */
public Constant resolveCase(
BlockScope scope,
- TypeBinding switchType,
+ TypeBinding switchExpressionType,
SwitchStatement switchStatement) {
scope.switchCase = this; // record entering in a switch case block
@@ -87,21 +93,36 @@ public class CaseStatement extends Statement {
// on error the last default will be the selected one ...
switchStatement.defaultCase = this;
- return null;
+ return NotAConstant;
}
// add into the collection of cases of the associated switch statement
switchStatement.cases[switchStatement.caseCount++] = this;
+ // tag constant name with enum type for privileged access to its members
+ if (switchExpressionType.isEnum() && (constantExpression instanceof SingleNameReference)) {
+ ((SingleNameReference) constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
+ }
TypeBinding caseType = constantExpression.resolveType(scope);
- if (caseType == null || switchType == null) return null;
- if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchType))
- return constantExpression.constant;
- if (caseType.isCompatibleWith(switchType))
+ if (caseType == null || switchExpressionType == null) return NotAConstant;
+ if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
+ || caseType.isCompatibleWith(switchExpressionType)) {
+ if (caseType.isEnum()) {
+ this.isEnumConstant = true;
+ if (constantExpression instanceof NameReference
+ && (constantExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
+ if (constantExpression instanceof QualifiedNameReference) {
+ scope.problemReporter().cannotUseQualifiedEnumConstantInCaseLabel((QualifiedNameReference)constantExpression);
+ }
+ return Constant.fromValue(((NameReference)constantExpression).fieldBinding().id); // ordinal value
+ }
+ } else {
+ return constantExpression.constant;
+ }
+ } else if (scope.isBoxingCompatibleWith(switchExpressionType, caseType)) {
+ constantExpression.computeConversion(scope, caseType, switchExpressionType);
return constantExpression.constant;
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
- constantExpression,
- caseType,
- switchType);
- return null;
+ }
+ scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
+ return NotAConstant;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index ecfe767..79e4922 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -11,7 +11,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -23,6 +22,7 @@ public class CastExpression extends Expression {
public Expression expression;
public Expression type;
+ public TypeBinding expectedType; // when assignment conversion to a given expected type: String s = (String) t;
//expression.implicitConversion holds the cast for baseType casting
public CastExpression(Expression expression, Expression type) {
@@ -54,172 +54,6 @@ public class CastExpression extends Expression {
}
/**
- * Returns false if the cast is unnecessary
- */
- public final boolean checkCastTypesCompatibility(
- BlockScope scope,
- TypeBinding castType,
- TypeBinding expressionType) {
-
- // see specifications 5.5
- // handle errors and process constant when needed
-
- // if either one of the type is null ==>
- // some error has been already reported some where ==>
- // we then do not report an obvious-cascade-error.
-
- if (castType == null || expressionType == null) return true;
-
- // identity conversion cannot be performed upfront, due to side-effects
- // like constant propagation
-
- if (castType.isBaseType()) {
- if (expressionType.isBaseType()) {
- if (expressionType == castType) {
- expression.implicitWidening(castType, expressionType);
- constant = expression.constant; //use the same constant
- return false;
- }
- boolean necessary = false;
- if (expressionType.isCompatibleWith(castType)
- || (necessary = BaseTypeBinding.isNarrowing(castType.id, expressionType.id))) {
- expression.implicitConversion = (castType.id << 4) + expressionType.id;
- if (expression.constant != Constant.NotAConstant) {
- constant = expression.constant.castTo(expression.implicitConversion);
- }
- return necessary;
-
- }
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return true;
- }
-
- //-----------cast to something which is NOT a base type--------------------------
- if (expressionType == NullBinding) {
- // if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
- // needRuntimeCheckcast = true;
- // }
- return false; //null is compatible with every thing
- }
- if (expressionType.isBaseType()) {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return true;
- }
-
- if (expressionType.isArrayType()) {
- if (castType == expressionType) return false; // identity conversion
-
- if (castType.isArrayType()) {
- //------- (castType.isArray) expressionType.isArray -----------
- TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
- if (exprElementType.isBaseType()) {
- // <---stop the recursion-------
- if (((ArrayBinding) castType).elementsType(scope) == exprElementType) {
- this.bits |= NeedRuntimeCheckCastMASK;
- } else {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- }
- return true;
- }
- // recursively on the elements...
- return checkCastTypesCompatibility(
- scope,
- ((ArrayBinding) castType).elementsType(scope),
- exprElementType);
- } else if (
- castType.isClass()) {
- //------(castType.isClass) expressionType.isArray ---------------
- if (castType.id == T_Object) {
- return false;
- }
- } else { //------- (castType.isInterface) expressionType.isArray -----------
- if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
- this.bits |= NeedRuntimeCheckCastMASK;
- return true;
- }
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return true;
- }
-
- if (expressionType.isClass()) {
- if (castType.isArrayType()) {
- // ---- (castType.isArray) expressionType.isClass -------
- if (expressionType.id == T_Object) { // potential runtime error
- this.bits |= NeedRuntimeCheckCastMASK;
- return true;
- }
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
- if (expressionType.isCompatibleWith(castType)){ // no runtime error
- if (castType.id == T_String) constant = expression.constant; // (String) cst is still a constant
- return false;
- }
- if (castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- this.bits |= NeedRuntimeCheckCastMASK;
- return true;
- }
- } else { // ----- (castType.isInterface) expressionType.isClass -------
- if (expressionType.isCompatibleWith(castType))
- return false;
- if (!((ReferenceBinding) expressionType).isFinal()) {
- // a subclass may implement the interface ==> no check at compile time
- this.bits |= NeedRuntimeCheckCastMASK;
- return true;
- }
- // no subclass for expressionType, thus compile-time check is valid
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return true;
- }
-
- // if (expressionType.isInterface()) { cannot be anything else
- if (castType.isArrayType()) {
- // ----- (castType.isArray) expressionType.isInterface ------
- if (expressionType.id == T_JavaLangCloneable
- || expressionType.id == T_JavaIoSerializable) {// potential runtime error
- this.bits |= NeedRuntimeCheckCastMASK;
- } else {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- }
- return true;
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
- if (castType.id == T_Object) { // no runtime error
- return false;
- }
- if (((ReferenceBinding) castType).isFinal()) {
- // no subclass for castType, thus compile-time check is valid
- if (!castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return true;
- }
- }
- } else { // ----- (castType.isInterface) expressionType.isInterface -------
- if (expressionType.isCompatibleWith(castType)) {
- return false;
- }
- if (!castType.isCompatibleWith(expressionType)) {
- MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
- MethodBinding[] expressionTypeMethods =
- ((ReferenceBinding) expressionType).methods();
- int exprMethodsLength = expressionTypeMethods.length;
- for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
- for (int j = 0; j < exprMethodsLength; j++) {
- if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
- && (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
- && castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- }
- }
- }
- }
- this.bits |= NeedRuntimeCheckCastMASK;
- return true;
- }
-
- /**
* Casting an enclosing instance will considered as useful if removing it would actually bind to a different type
*/
public static void checkNeedForEnclosingInstanceCast(BlockScope scope, Expression enclosingInstance, TypeBinding enclosingInstanceType, TypeBinding memberType) {
@@ -363,10 +197,10 @@ public class CastExpression extends Expression {
}
if (leftIsCast || rightIsCast) {
if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String
- if (alternateLeftTypeId == T_String) {
- alternateRightTypeId = T_Object;
- } else if (alternateRightTypeId == T_String) {
- alternateLeftTypeId = T_Object;
+ if (alternateLeftTypeId == T_JavaLangString) {
+ alternateRightTypeId = T_JavaLangObject;
+ } else if (alternateRightTypeId == T_JavaLangString) {
+ alternateLeftTypeId = T_JavaLangObject;
} else {
return; // invalid operator
}
@@ -377,8 +211,8 @@ public class CastExpression extends Expression {
// <<16 <<12 <<8 <<4 <<0
final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
- if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left, TypeBinding.wellKnownType(scope, left.implicitConversion >> 4));
- if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope, right.implicitConversion >> 4));
+ if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left, TypeBinding.wellKnownType(scope, (left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4));
+ if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope, (right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4));
}
}
}
@@ -386,6 +220,7 @@ public class CastExpression extends Expression {
private static void checkAlternateBinding(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) {
InvocationSite fakeInvocationSite = new InvocationSite(){
+ public TypeBinding[] genericTypeArguments() { return null; }
public boolean isSuperAccess(){ return invocationSite.isSuperAccess(); }
public boolean isTypeAccess() { return invocationSite.isTypeAccess(); }
public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */}
@@ -410,6 +245,33 @@ public class CastExpression extends Expression {
}
}
}
+
+ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ if (match == castType) {
+ if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ if (castType.isBoundParameterizedType() || castType.isGenericType()) {
+ if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+ if (isNarrowing ? !expressionType.isEquivalentTo(match) : !match.isEquivalentTo(castType)) {
+ scope.problemReporter().unsafeCast(this);
+ return true;
+ }
+ if ((castType.tagBits & TagBits.HasDirectWildcard) == 0) {
+ if ((!match.isParameterizedType() && !match.isGenericType())
+ || expressionType.isRawType()) {
+ scope.problemReporter().unsafeCast(this);
+ return true;
+ }
+ }
+ }
+ if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+
/**
* Cast expression code generation
*
@@ -421,7 +283,7 @@ public class CastExpression extends Expression {
BlockScope currentScope,
CodeStream codeStream,
boolean valueRequired) {
-
+
int pc = codeStream.position;
boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0;
if (constant != NotAConstant) {
@@ -429,8 +291,11 @@ public class CastExpression extends Expression {
codeStream.generateConstant(constant, implicitConversion);
if (needRuntimeCheckcast) {
codeStream.checkcast(this.resolvedType);
- if (!valueRequired)
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(this.implicitConversion);
+ } else {
codeStream.pop();
+ }
}
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -442,8 +307,11 @@ public class CastExpression extends Expression {
valueRequired || needRuntimeCheckcast);
if (needRuntimeCheckcast) {
codeStream.checkcast(this.resolvedType);
- if (!valueRequired)
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
codeStream.pop();
+ }
} else {
if (valueRequired)
codeStream.generateImplicitConversion(implicitConversion);
@@ -459,6 +327,17 @@ public class CastExpression extends Expression {
return current;
}
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#localVariableBinding()
+ */
+ public LocalVariableBinding localVariableBinding() {
+ return this.expression.localVariableBinding();
+ }
+
+ public int nullStatus(FlowInfo flowInfo) {
+ return this.expression.nullStatus(flowInfo);
+ }
+
public StringBuffer printExpression(int indent, StringBuffer output) {
output.append('(');
@@ -466,6 +345,10 @@ public class CastExpression extends Expression {
return expression.printExpression(0, output);
}
+ public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+ scope.problemReporter().typeCastError(this, castType, expressionType);
+ }
+
public TypeBinding resolveType(BlockScope scope) {
// compute a new constant if the cast is effective
@@ -480,25 +363,67 @@ public class CastExpression extends Expression {
&& ((type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // no extra parenthesis around type: ((A))exp
this.resolvedType = type.resolveType(scope);
+ expression.setExpectedType(this.resolvedType); // needed in case of generic method invocation
TypeBinding expressionType = expression.resolveType(scope);
if (this.resolvedType != null && expressionType != null) {
- boolean necessary = checkCastTypesCompatibility(scope, this.resolvedType, expressionType);
- if (!necessary && this.expression.resolvedType != null) { // cannot do better if expression is not bound
- this.bits |= UnnecessaryCastMask;
+ checkCastTypesCompatibility(scope, this.resolvedType, expressionType, this.expression);
+ this.expression.computeConversion(scope, this.resolvedType, expressionType);
+ if ((this.bits & UnnecessaryCastMask) != 0) {
if ((this.bits & IgnoreNeedForCastCheckMASK) == 0) {
- scope.problemReporter().unnecessaryCast(this);
+ if (!usedForGenericMethodReturnTypeInference()) // used for generic type inference ?
+ scope.problemReporter().unnecessaryCast(this);
}
}
}
return this.resolvedType;
- } else { // expression as a cast !!!!!!!!
+ } else { // expression as a cast
TypeBinding expressionType = expression.resolveType(scope);
if (expressionType == null) return null;
scope.problemReporter().invalidTypeReference(type);
return null;
}
}
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void setExpectedType(TypeBinding expectedType) {
+ this.expectedType = expectedType;
+ }
+ /**
+ * Determines whether apparent unnecessary cast wasn't actually used to
+ * perform return type inference of generic method invocation.
+ */
+ private boolean usedForGenericMethodReturnTypeInference() {
+ if (this.expression instanceof MessageSend) {
+ MethodBinding method = ((MessageSend)this.expression).binding;
+ if (method instanceof ParameterizedGenericMethodBinding
+ && ((ParameterizedGenericMethodBinding)method).inferredReturnType) {
+ if (this.expectedType == null)
+ return true;
+ if (this.resolvedType != this.expectedType)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsNeedCheckCast()
+ */
+ public void tagAsNeedCheckCast() {
+ this.bits |= NeedRuntimeCheckCastMASK;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope, TypeBinding)
+ */
+ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+ if (this.expression.resolvedType == null) return; // cannot do better if expression is not bound
+ this.bits |= UnnecessaryCastMask;
+ }
+
public void traverse(
ASTVisitor visitor,
BlockScope blockScope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
index c2d90b0..8aad9ab 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
@@ -84,11 +84,9 @@ private void computeValue() {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
- if ((implicitConversion >> 4) == T_char)
- codeStream.generateInlinedValue(value);
- else
- codeStream.generateConstant(constant, implicitConversion);
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public TypeBinding literalType(BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/src/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 4a4136e..4e35315 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -35,10 +36,11 @@ public class ClassLiteralAccess extends Expression {
// if reachable, request the addition of a synthetic field for caching the class descriptor
SourceTypeBinding sourceType =
currentScope.outerMostMethodScope().enclosingSourceType();
- if (!(sourceType.isInterface()
- // no field generated in interface case (would'nt verify) see 1FHHEZL
- || sourceType.isBaseType())) {
- syntheticField = sourceType.addSyntheticField(targetType, currentScope);
+ if ((!(sourceType.isInterface()
+ // no field generated in interface case (would'nt verify) see 1FHHEZL
+ || sourceType.isBaseType()))
+ && currentScope.environment().options.sourceLevel <= ClassFileConstants.JDK1_5) {
+ syntheticField = sourceType.addSyntheticFieldForClassLiteral(targetType, currentScope);
}
return flowInfo;
}
@@ -57,8 +59,10 @@ public class ClassLiteralAccess extends Expression {
int pc = codeStream.position;
// in interface case, no caching occurs, since cannot make a cache field for interface
- if (valueRequired)
+ if (valueRequired) {
codeStream.generateClassLiteralAccessForType(type.resolvedType, syntheticField);
+ codeStream.generateImplicitConversion(this.implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
@@ -70,16 +74,24 @@ public class ClassLiteralAccess extends Expression {
public TypeBinding resolveType(BlockScope scope) {
constant = NotAConstant;
- if ((targetType = type.resolveType(scope)) == null)
+ if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
return null;
if (targetType.isArrayType()
&& ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
scope.problemReporter().cannotAllocateVoidArray(this);
return null;
+ } else if (targetType.isTypeVariable()) {
+ scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)targetType, this);
}
-
- return this.resolvedType = scope.getJavaLangClass();
+ ReferenceBinding classType = scope.getJavaLangClass();
+ if (classType.isGenericType()) {
+ // Integer.class --> Class, perform boxing of base types (int.class --> Class)
+ this.resolvedType = scope.createParameterizedType(classType, new TypeBinding[]{ scope.boxing(targetType) }, null/*not a member*/);
+ } else {
+ this.resolvedType = classType;
+ }
+ return this.resolvedType;
}
public void traverse(
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/src/org/eclipse/jdt/internal/compiler/ast/Clinit.java
index 2bbac9c..22dbe6d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Clinit.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Clinit.java
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
@@ -20,15 +21,13 @@ import org.eclipse.jdt.internal.compiler.problem.*;
public class Clinit extends AbstractMethodDeclaration {
- public final static char[] ConstantPoolName = "".toCharArray(); //$NON-NLS-1$
-
private FieldBinding assertionSyntheticFieldBinding = null;
private FieldBinding classLiteralSyntheticField = null;
public Clinit(CompilationResult compilationResult) {
super(compilationResult);
modifiers = 0;
- selector = ConstantPoolName;
+ selector = TypeConstants.CLINIT;
}
public void analyseCode(
@@ -60,7 +59,7 @@ public class Clinit extends AbstractMethodDeclaration {
&& (!flowInfo.isDefinitelyAssigned(fields[i]))) {
scope.problemReporter().uninitializedBlankFinalField(
field,
- scope.referenceType().declarationOf(field));
+ scope.referenceType().declarationOf(field.original()));
// can complain against the field decl, since only one
}
}
@@ -150,7 +149,7 @@ public class Clinit extends AbstractMethodDeclaration {
if (this.assertionSyntheticFieldBinding != null) {
// generate code related to the activation of assertion for this class
codeStream.generateClassLiteralAccessForType(
- classScope.enclosingSourceType(),
+ classScope.enclosingSourceType(),
classLiteralSyntheticField);
codeStream.invokeJavaLangClassDesiredAssertionStatus();
Label falseLabel = new Label(codeStream);
@@ -163,15 +162,63 @@ public class Clinit extends AbstractMethodDeclaration {
jumpLabel.place();
codeStream.putstatic(this.assertionSyntheticFieldBinding);
}
- // generate initializers
- if (declaringType.fields != null) {
- for (int i = 0, max = declaringType.fields.length; i < max; i++) {
- FieldDeclaration fieldDecl;
- if ((fieldDecl = declaringType.fields[i]).isStatic()) {
- fieldDecl.generateCode(staticInitializerScope, codeStream);
+ // generate static fields/initializers/enum constants
+ final FieldDeclaration[] fieldDeclarations = declaringType.fields;
+ if (declaringType.kind() == IGenericType.ENUM_DECL) {
+ int enumCount = 0;
+ int notEnumConstants = 0;
+ if (fieldDeclarations != null) {
+ for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+ FieldDeclaration fieldDecl = fieldDeclarations[i];
+ if (fieldDecl.isStatic()) {
+ if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ fieldDecl.generateCode(staticInitializerScope, codeStream);
+ enumCount++;
+ } else {
+ notEnumConstants++;
+ }
+ }
+ }
+ }
+ // enum need to initialize $VALUES synthetic cache of enum constants
+ if (enumCount > 0) {
+ if (fieldDeclarations != null) {
+ // $VALUES := new []
+ codeStream.generateInlinedValue(enumCount);
+ codeStream.anewarray(declaringType.binding);
+ for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+ FieldDeclaration fieldDecl = fieldDeclarations[i];
+ // $VALUES[i] =
+ if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ codeStream.dup();
+ codeStream.generateInlinedValue(fieldDecl.binding.id);
+ codeStream.getstatic(fieldDecl.binding);
+ codeStream.aastore();
+ }
+ }
+ codeStream.putstatic(declaringType.enumValuesSyntheticfield);
+ }
+ }
+ if (notEnumConstants != 0) {
+ // if fields that are not enum constants need to be generated (static initializer/static field)
+ for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+ FieldDeclaration fieldDecl = fieldDeclarations[i];
+ if (fieldDecl.isStatic() && fieldDecl.getKind() != AbstractVariableDeclaration.ENUM_CONSTANT) {
+ fieldDecl.generateCode(staticInitializerScope, codeStream);
+ }
+ }
+ }
+ } else {
+ if (fieldDeclarations != null) {
+ for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
+ FieldDeclaration fieldDecl = fieldDeclarations[i];
+ if (fieldDecl.isStatic()) {
+ fieldDecl.generateCode(staticInitializerScope, codeStream);
+ }
}
}
}
+
if (codeStream.position == 0) {
// do not need to output a Clinit if no bytecodes
// so we reset the offset inside the byte array contents.
@@ -231,16 +278,17 @@ public class Clinit extends AbstractMethodDeclaration {
visitor.endVisit(this, classScope);
}
- // 1.4 feature
- public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding) {
+ public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding, boolean needClassLiteralField) {
this.assertionSyntheticFieldBinding = assertionSyntheticFieldBinding;
// we need to add the field right now, because the field infos are generated before the methods
SourceTypeBinding sourceType =
this.scope.outerMostMethodScope().enclosingSourceType();
- this.classLiteralSyntheticField =
- sourceType.addSyntheticField(sourceType, scope);
+ if (needClassLiteralField) {
+ this.classLiteralSyntheticField =
+ sourceType.addSyntheticFieldForClassLiteral(sourceType, scope);
+ }
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index d736614..df96e49 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -19,6 +19,8 @@ import org.eclipse.jdt.internal.compiler.problem.*;
public class CompilationUnitDeclaration
extends ASTNode
implements ProblemSeverities, ReferenceContext {
+
+ private static final char[] PACKAGE_INFO_FILE_NAME = "package-info.java".toCharArray(); //$NON-NLS-1$
public ImportReference currentPackage;
public ImportReference[] imports;
@@ -266,7 +268,12 @@ public class CompilationUnitDeclaration
}
public void resolve() {
-
+ if (this.currentPackage != null) {
+ if (this.currentPackage.annotations != null
+ && !CharOperation.endsWith(getFileName(), PACKAGE_INFO_FILE_NAME)) {
+ scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]);
+ }
+ }
try {
if (types != null) {
for (int i = 0, count = types.length; i < count; i++) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
index 47745f1..fda4ef3 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
@@ -54,6 +54,10 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.NON_NULL;
+ }
+
public String operatorToString() {
switch (operator) {
case PLUS :
@@ -94,23 +98,41 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
scope.problemReporter().expressionShouldBeAVariable(this.lhs);
return null;
}
- TypeBinding lhsType = lhs.resolveType(scope);
- TypeBinding expressionType = expression.resolveType(scope);
- if (lhsType == null || expressionType == null)
+ TypeBinding originalLhsType = lhs.resolveType(scope);
+ TypeBinding originalExpressionType = expression.resolveType(scope);
+ if (originalLhsType == null || originalExpressionType == null)
return null;
- int lhsId = lhsType.id;
- int expressionId = expressionType.id;
+ // autoboxing support
+ LookupEnvironment env = scope.environment();
+ TypeBinding lhsType = originalLhsType, expressionType = originalExpressionType;
+ boolean use15specifics = scope.environment().options.sourceLevel >= JDK1_5;
+ boolean unboxedLhs = false;
+ if (use15specifics) {
+ if (!lhsType.isBaseType() && expressionType.id != T_JavaLangString && expressionType.id != T_null) {
+ TypeBinding unboxedType = env.computeBoxingType(lhsType);
+ if (unboxedType != lhsType) {
+ lhsType = unboxedType;
+ unboxedLhs = true;
+ }
+ }
+ if (!expressionType.isBaseType() && lhsType.id != T_JavaLangString && lhsType.id != T_null) {
+ expressionType = env.computeBoxingType(expressionType);
+ }
+ }
+
if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) {
scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
return null;
}
- if (lhsId > 15 || expressionId > 15) {
- if (lhsId != T_String) { // String += Thread is valid whereas Thread += String is not
+ int lhsID = lhsType.id;
+ int expressionID = expressionType.id;
+ if (lhsID > 15 || expressionID > 15) {
+ if (lhsID != T_JavaLangString) { // String += Thread is valid whereas Thread += String is not
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
return null;
}
- expressionId = T_Object; // use the Object has tag table
+ expressionID = T_JavaLangObject; // use the Object has tag table
}
// the code is an int
@@ -119,28 +141,28 @@ public class CompoundAssignment extends Assignment implements OperatorIds {
// <<16 <<12 <<8 <<4 <<0
// the conversion is stored INTO the reference (info needed for the code gen)
- int result = OperatorExpression.OperatorSignatures[operator][ (lhsId << 4) + expressionId];
+ int result = OperatorExpression.OperatorSignatures[operator][ (lhsID << 4) + expressionID];
if (result == T_undefined) {
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
return null;
}
if (operator == PLUS){
- if(lhsId == T_JavaLangObject) {
+ if(lhsID == T_JavaLangObject) {
// += is illegal (39248)
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
return null;
} else {
// += is illegal
- if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
+ if ((lhsType.isNumericType() || lhsID == T_boolean) && !expressionType.isNumericType()){
scope.problemReporter().invalidOperator(this, lhsType, expressionType);
return null;
}
}
}
- lhs.implicitConversion = result >>> 12;
- expression.implicitConversion = (result >>> 4) & 0x000FF;
- assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
- return this.resolvedType = lhsType;
+ this.lhs.implicitConversion = (unboxedLhs ? UNBOXING : 0) | (result >>> 12);
+ this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (result >>> 8) & 0x0000F), originalExpressionType);
+ this.assignmentImplicitConversion = (unboxedLhs ? BOXING : 0) | (lhsID << 4) | (result & 0x0000F);
+ return this.resolvedType = originalLhsType;
}
public boolean restrainUsageToNumericTypes(){
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index cf86373..2572232 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -200,7 +201,7 @@ public class ConditionalExpression extends OperatorExpression {
boolean valueRequired) {
if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean) // constant
- || (valueIfTrue.implicitConversion >> 4) != T_boolean) { // non boolean values
+ || ((valueIfTrue.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_boolean) { // non boolean values
super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
return;
}
@@ -246,9 +247,7 @@ public class ConditionalExpression extends OperatorExpression {
if (needFalsePart) {
internalFalseLabel.place();
if (falseInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- falseInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
}
valueIfFalse.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
@@ -258,9 +257,7 @@ public class ConditionalExpression extends OperatorExpression {
}
// May loose some local variable initializations : affecting the local variable attributes
if (mergedInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- mergedInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
}
// no implicit conversion for boolean values
codeStream.updateLastRecordedEndPC(codeStream.position);
@@ -281,17 +278,30 @@ public class ConditionalExpression extends OperatorExpression {
public TypeBinding resolveType(BlockScope scope) {
// specs p.368
constant = NotAConstant;
+ LookupEnvironment env = scope.environment();
+ boolean use15specifics = env.options.sourceLevel >= ClassFileConstants.JDK1_5;
TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
if (valueIfTrue instanceof CastExpression) valueIfTrue.bits |= IgnoreNeedForCastCheckMASK; // will check later on
- TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+ TypeBinding originalValueIfTrueType = valueIfTrue.resolveType(scope);
if (valueIfFalse instanceof CastExpression) valueIfFalse.bits |= IgnoreNeedForCastCheckMASK; // will check later on
- TypeBinding valueIfFalseType = valueIfFalse.resolveType(scope);
+ TypeBinding originalValueIfFalseType = valueIfFalse.resolveType(scope);
- if (conditionType == null || valueIfTrueType == null || valueIfFalseType == null)
+ if (conditionType == null || originalValueIfTrueType == null || originalValueIfFalseType == null)
return null;
+ TypeBinding valueIfTrueType = originalValueIfTrueType;
+ TypeBinding valueIfFalseType = originalValueIfFalseType;
+ if (use15specifics) {
+ if (valueIfTrueType != NullBinding && valueIfTrueType.isBaseType()) {
+ if (!valueIfFalseType.isBaseType()) {
+ valueIfFalseType = env.computeBoxingType(valueIfFalseType);
+ }
+ } else if (valueIfFalseType != NullBinding && valueIfFalseType.isBaseType()) {
+ valueIfTrueType = env.computeBoxingType(valueIfTrueType);
+ }
+ }
// Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
Constant condConstant, trueConstant, falseConstant;
if ((condConstant = condition.constant) != NotAConstant
@@ -302,8 +312,8 @@ public class ConditionalExpression extends OperatorExpression {
constant = condConstant.booleanValue() ? trueConstant : falseConstant;
}
if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion
- valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
- valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
+ valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
if (valueIfTrueType == BooleanBinding) {
this.optimizedIfTrueConstant = valueIfTrue.optimizedBooleanConstant();
this.optimizedIfFalseConstant = valueIfFalse.optimizedBooleanConstant();
@@ -326,16 +336,16 @@ public class ConditionalExpression extends OperatorExpression {
// (Short x Byte) or (Byte x Short)"
if ((valueIfTrueType == ByteBinding && valueIfFalseType == ShortBinding)
|| (valueIfTrueType == ShortBinding && valueIfFalseType == ByteBinding)) {
- valueIfTrue.implicitWidening(ShortBinding, valueIfTrueType);
- valueIfFalse.implicitWidening(ShortBinding, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, ShortBinding, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, ShortBinding, originalValueIfFalseType);
return this.resolvedType = ShortBinding;
}
// x constant(Int) ---> and reciprocally
if ((valueIfTrueType == ByteBinding || valueIfTrueType == ShortBinding || valueIfTrueType == CharBinding)
&& (valueIfFalseType == IntBinding
&& valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) {
- valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
- valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType);
return this.resolvedType = valueIfTrueType;
}
if ((valueIfFalseType == ByteBinding
@@ -343,35 +353,35 @@ public class ConditionalExpression extends OperatorExpression {
|| valueIfFalseType == CharBinding)
&& (valueIfTrueType == IntBinding
&& valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
- valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
- valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
return this.resolvedType = valueIfFalseType;
}
// Manual binary numeric promotion
// int
if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_int)
&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_int)) {
- valueIfTrue.implicitWidening(IntBinding, valueIfTrueType);
- valueIfFalse.implicitWidening(IntBinding, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, IntBinding, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, IntBinding, originalValueIfFalseType);
return this.resolvedType = IntBinding;
}
// long
if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
- valueIfTrue.implicitWidening(LongBinding, valueIfTrueType);
- valueIfFalse.implicitWidening(LongBinding, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, LongBinding, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, LongBinding, originalValueIfFalseType);
return this.resolvedType = LongBinding;
}
// float
if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float)
&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
- valueIfTrue.implicitWidening(FloatBinding, valueIfTrueType);
- valueIfFalse.implicitWidening(FloatBinding, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, FloatBinding, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, FloatBinding, originalValueIfFalseType);
return this.resolvedType = FloatBinding;
}
// double
- valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
- valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, DoubleBinding, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, DoubleBinding, originalValueIfFalseType);
return this.resolvedType = DoubleBinding;
}
// Type references (null null is already tested)
@@ -384,15 +394,24 @@ public class ConditionalExpression extends OperatorExpression {
return null;
}
if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) {
- valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
- valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, valueIfTrueType, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, valueIfTrueType, originalValueIfFalseType);
return this.resolvedType = valueIfTrueType;
}
if (valueIfTrueType.isCompatibleWith(valueIfFalseType)) {
- valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
- valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ valueIfTrue.computeConversion(scope, valueIfFalseType, originalValueIfTrueType);
+ valueIfFalse.computeConversion(scope, valueIfFalseType, originalValueIfFalseType);
return this.resolvedType = valueIfFalseType;
}
+ // 1.5 addition: allow most common supertype
+ if (use15specifics) {
+ TypeBinding commonType = scope.lowerUpperBound(new TypeBinding[] { valueIfTrueType, valueIfFalseType });
+ if (commonType != null) {
+ valueIfTrue.computeConversion(scope, commonType, valueIfTrueType);
+ valueIfFalse.computeConversion(scope, commonType, valueIfFalseType);
+ return this.resolvedType = commonType;
+ }
+ }
scope.problemReporter().conditionalArgumentsIncompatibleTypes(
this,
valueIfTrueType,
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 7170bbf..892b91b 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -24,8 +24,9 @@ import org.eclipse.jdt.internal.compiler.problem.*;
public class ConstructorDeclaration extends AbstractMethodDeclaration {
public ExplicitConstructorCall constructorCall;
- public final static char[] ConstantPoolName = "".toCharArray(); //$NON-NLS-1$
+
public boolean isDefaultConstructor = false;
+ public TypeParameter[] typeParameters;
public ConstructorDeclaration(CompilationResult compilationResult){
super(compilationResult);
@@ -76,6 +77,13 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
}
}
+ // tag parameters as being set
+ if (this.arguments != null) {
+ for (int i = 0, count = this.arguments.length; i < count; i++) {
+ flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
+ }
+ }
+
// propagate to constructor call
if (constructorCall != null) {
// if calling 'this(...)', then flag all non-static fields as definitely
@@ -212,7 +220,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
classFile.generateMethodInfoHeader(binding);
int methodAttributeOffset = classFile.contentsOffset;
- int attributeNumber = classFile.generateMethodInfoAttribute(binding);
+ int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
if ((!binding.isNative()) && (!binding.isAbstract())) {
TypeDeclaration declaringType = classScope.referenceContext;
@@ -224,18 +232,19 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
// initialize local positions - including initializer scope.
ReferenceBinding declaringClass = binding.declaringClass;
- int argSlotSize = 1; // this==aload0
-
+ int enumOffset = declaringClass.isEnum() ? 2 : 0; // String name, int ordinal
+ int argSlotSize = 1 + enumOffset; // this==aload0
+
if (declaringClass.isNestedType()){
NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables();
scope.computeLocalVariablePositions(// consider synthetic arguments if any
- nestedType.enclosingInstancesSlotSize + 1,
+ nestedType.enclosingInstancesSlotSize + 1 + enumOffset,
codeStream);
argSlotSize += nestedType.enclosingInstancesSlotSize;
argSlotSize += nestedType.outerLocalVariablesSlotSize;
} else {
- scope.computeLocalVariablePositions(1, codeStream);
+ scope.computeLocalVariablePositions(1 + enumOffset, codeStream);
}
if (arguments != null) {
@@ -321,13 +330,10 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
return true;
}
- /**
+ /*
* Returns true if the constructor is directly involved in a cycle.
* Given most constructors aren't, we only allocate the visited list
* lazily.
- *
- * @param visited
- * @return
*/
public boolean isRecursive(ArrayList visited) {
@@ -340,7 +346,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
}
ConstructorDeclaration targetConstructor =
- ((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding));
+ ((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding.original()));
if (this == targetConstructor) return true; // direct case
if (visited == null) { // lazy allocation
@@ -359,10 +365,10 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
//fill up the constructor body with its statements
if (ignoreFurtherInvestigation)
return;
- if (isDefaultConstructor){
- constructorCall = SuperReference.implicitSuperConstructorCall();
- constructorCall.sourceStart = sourceStart;
- constructorCall.sourceEnd = sourceEnd;
+ if (isDefaultConstructor && this.constructorCall == null){
+ this.constructorCall = SuperReference.implicitSuperConstructorCall();
+ this.constructorCall.sourceStart = this.sourceStart;
+ this.constructorCall.sourceEnd = this.sourceEnd;
return;
}
parser.parse(this, unit);
@@ -406,11 +412,14 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
scope.problemReporter().missingReturnType(this);
}
+ if (this.binding != null && this.binding.declaringClass.isAnnotationType()) {
+ scope.problemReporter().annotationTypeDeclarationCannotHaveConstructor(this);
+ }
// if null ==> an error has occurs at parsing time ....
if (this.constructorCall != null) {
// e.g. using super() in java.lang.Object
if (this.binding != null
- && this.binding.declaringClass.id == T_Object
+ && this.binding.declaringClass.id == T_JavaLangObject
&& this.constructorCall.accessMode != ExplicitConstructorCall.This) {
if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
@@ -430,7 +439,19 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
ASTVisitor visitor,
ClassScope classScope) {
+
if (visitor.visit(this, classScope)) {
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ if (this.typeParameters != null) {
+ int typeParametersLength = this.typeParameters.length;
+ for (int i = 0; i < typeParametersLength; i++) {
+ this.typeParameters[i].traverse(visitor, scope);
+ }
+ }
if (arguments != null) {
int argumentLength = arguments.length;
for (int i = 0; i < argumentLength; i++)
@@ -451,4 +472,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
}
visitor.endVisit(this, classScope);
}
+ public TypeParameter[] typeParameters() {
+ return this.typeParameters;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index 0dc995d..a12254a 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -59,11 +59,12 @@ public class DoStatement extends Statement {
int previousMode = flowInfo.reachMode();
+ FlowInfo actionInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
if ((action != null) && !action.isEmptyBlock()) {
- flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
+ actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
// code generation can be optimized when no need to continue in the loop
- if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+ if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
continueLabel = null;
}
}
@@ -72,24 +73,24 @@ public class DoStatement extends Statement {
* do { if (true) break; else blank = 0; } while(false);
* blank = 1; // may be initialized already
*/
- flowInfo.setReachMode(previousMode);
+ actionInfo.setReachMode(previousMode);
- flowInfo =
+ actionInfo =
condition.analyseCode(
currentScope,
loopingContext,
(action == null
- ? flowInfo
- : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
+ ? actionInfo
+ : (actionInfo.mergedWith(loopingContext.initsOnContinue))));
if (!isConditionOptimizedFalse && continueLabel != null) {
- loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+ loopingContext.complainOnDeferredChecks(currentScope, actionInfo);
}
// end of loop
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
loopingContext.initsOnBreak,
isConditionOptimizedTrue,
- flowInfo.initsWhenFalse(),
+ actionInfo.initsWhenFalse().addInitializationsFrom(flowInfo), // recover null inits from before condition analysis
false, // never consider opt false case for DO loop, since break can always occur (47776)
!isConditionTrue /*do{}while(true); unreachable(); */);
mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -155,7 +156,7 @@ public class DoStatement extends Statement {
public void resolve(BlockScope scope) {
TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
- condition.implicitWidening(type, type);
+ condition.computeConversion(scope, type, type);
if (action != null)
action.resolve(scope);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
index 139c813..1c8a8c1 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
@@ -14,58 +14,100 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.util.FloatUtil;
public class DoubleLiteral extends NumberLiteral {
double value;
-public DoubleLiteral(char[] token, int s, int e) {
- super(token, s,e);
-}
-public void computeConstant() {
-
- //the source is correctly formated so the exception should never occurs
+ public DoubleLiteral(char[] token, int s, int e) {
+ super(token, s, e);
+ }
+ public void computeConstant() {
+ Double computedValue;
+ try {
+ computedValue = Double.valueOf(String.valueOf(source));
+ } catch (NumberFormatException e) {
+ // hex floating point literal
+ // being rejected by 1.4 libraries where Double.valueOf(...) doesn't handle hex decimal floats
+ try {
+ double v = FloatUtil.valueOfHexDoubleLiteral(source);
+ if (v == Double.POSITIVE_INFINITY) {
+ // error: the number is too large to represent
+ return;
+ }
+ if (Double.isNaN(v)) {
+ // error: the number is too small to represent
+ return;
+ }
+ value = v;
+ constant = Constant.fromValue(v);
+ } catch (NumberFormatException e1) {
+ // if the computation of the constant fails
+ }
+ return;
+ }
- Double computedValue;
- try { computedValue = Double.valueOf(String.valueOf(source));}
- catch(NumberFormatException e){return ;} //how can it happen ????
-
- if (computedValue.doubleValue() > Double.MAX_VALUE) return ; //may be Infinity
- if (computedValue.doubleValue() < Double.MIN_VALUE)
- { //only a true 0 can be made of zeros
- //2.00000000000000000e-324 is illegal ....
- label :
- for (int i=0;i Double.MAX_VALUE) {
+ // error: the number is too large to represent
+ return;
+ }
+ if (doubleValue < Double.MIN_VALUE) {
+ // see 1F6IGUU
+ // a true 0 only has '0' and '.' in mantissa
+ // 1.0e-5000d is non-zero, but underflows to 0
+ boolean isHexaDecimal = false;
+ label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d
+ switch (source[i]) {
case '0' :
case '.' :
+ break;
+ case 'x' :
+ case 'X' :
+ isHexaDecimal = true;
+ break;
+ case 'e' :
+ case 'E' :
+ case 'f' :
+ case 'F' :
case 'd' :
- case 'D' : break ;
- case 'e' :
- case 'E' : break label ; //exposant are valid....!
- default : return;}}} //error
-
- constant = Constant.fromValue(value = computedValue.doubleValue());}
-/**
- * Code generation for the double literak
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- if (valueRequired)
- if ((implicitConversion >> 4) == T_double)
- codeStream.generateInlinedValue(value);
- else
+ case 'D' :
+ if (isHexaDecimal) {
+ return;
+ }
+ // starting the exponent - mantissa is all zero
+ // no exponent - mantissa is all zero
+ break label;
+ case 'p' :
+ case 'P' :
+ break label;
+ default :
+ // error: the number is too small to represent
+ return;
+ }
+ }
+ }
+ value = doubleValue;
+ constant = Constant.fromValue(value);
+ }
+ /**
+ * Code generation for the double literak
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ int pc = codeStream.position;
+ if (valueRequired) {
codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public TypeBinding literalType(BlockScope scope) {
- return DoubleBinding;
-}
-public void traverse(ASTVisitor visitor, BlockScope blockScope) {
- visitor.visit(this, blockScope);
- visitor.endVisit(this, blockScope);
-}
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+ public TypeBinding literalType(BlockScope scope) {
+ return DoubleBinding;
+ }
+ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 0caeb81..4b2fec9 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -19,386 +18,313 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
public class EqualExpression extends BinaryExpression {
-public EqualExpression(Expression left, Expression right,int operator) {
- super(left,right,operator);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
- if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
- if (left.constant.booleanValue()) { // true == anything
- // this is equivalent to the right argument inits
- return right.analyseCode(currentScope, flowContext, flowInfo);
- } else { // false == anything
- // this is equivalent to the right argument inits negated
- return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
- }
- }
- if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
- if (right.constant.booleanValue()) { // anything == true
- // this is equivalent to the right argument inits
- return left.analyseCode(currentScope, flowContext, flowInfo);
- } else { // anything == false
- // this is equivalent to the right argument inits negated
- return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
- }
- }
- return right.analyseCode(
- currentScope, flowContext,
- left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
- } else { //NOT_EQUAL :
- if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
- if (!left.constant.booleanValue()) { // false != anything
- // this is equivalent to the right argument inits
- return right.analyseCode(currentScope, flowContext, flowInfo);
- } else { // true != anything
- // this is equivalent to the right argument inits negated
- return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
- }
- }
- if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
- if (!right.constant.booleanValue()) { // anything != false
- // this is equivalent to the right argument inits
- return left.analyseCode(currentScope, flowContext, flowInfo);
- } else { // anything != true
- // this is equivalent to the right argument inits negated
- return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
- }
- }
- return right.analyseCode(
- currentScope, flowContext,
- left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits();
+ public EqualExpression(Expression left, Expression right,int operator) {
+ super(left,right,operator);
}
-}
-public final boolean areTypesCastCompatible(BlockScope scope, TypeBinding castType, TypeBinding expressionType) {
- //see specifications 5.5
- //A more complete version of this method is provided on
- //CastExpression (it deals with constant and need runtime checkcast)
-
- if (castType == expressionType) return true;
-
- //========ARRAY===============
- if (expressionType.isArrayType()) {
- if (castType.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
- TypeBinding expressionEltType = ((ArrayBinding) expressionType).elementsType(scope);
- if (expressionEltType.isBaseType())
- // <---stop the recursion-------
- return ((ArrayBinding) castType).elementsType(scope) == expressionEltType;
- //recursivly on the elts...
- return areTypesCastCompatible(scope, ((ArrayBinding) castType).elementsType(scope), expressionEltType);
+ public void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
+
+ LocalVariableBinding local = this.left.localVariableBinding();
+ if (local != null) {
+ checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, right.nullStatus(flowInfo), this.left);
}
- if (castType.isBaseType()) {
- return false;
+ local = this.right.localVariableBinding();
+ if (local != null) {
+ checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, left.nullStatus(flowInfo), this.right);
}
- if (castType.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------
- if (castType.id == T_Object)
- return true;
- return false;
- }
- if (castType.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray -----------
- if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
- return true;
- }
- return false;
- }
-
- return false;
}
-
- //------------(castType) null--------------
- if (expressionType == NullBinding) {
- return !castType.isBaseType();
- }
-
- //========BASETYPE==============
- if (expressionType.isBaseType()) {
- return false;
+ private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
+ switch (nullStatus) {
+ case FlowInfo.NULL :
+ flowContext.recordUsingNullReference(scope, local, reference, FlowInfo.NULL, flowInfo);
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+ initsWhenTrue.markAsDefinitelyNull(local); // from thereon it is set
+ initsWhenFalse.markAsDefinitelyNonNull(local); // from thereon it is set
+ } else {
+ initsWhenTrue.markAsDefinitelyNonNull(local); // from thereon it is set
+ initsWhenFalse.markAsDefinitelyNull(local); // from thereon it is set
+ }
+ break;
+ case FlowInfo.NON_NULL :
+ flowContext.recordUsingNullReference(scope, local, reference, FlowInfo.NON_NULL, flowInfo);
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+ initsWhenTrue.markAsDefinitelyNonNull(local); // from thereon it is set
+ }
+ break;
+ }
}
-
-
- //========REFERENCE TYPE===================
-
- if (expressionType.isClass()) {
- if (castType.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
- if (expressionType.id == T_Object)
- return true;
- }
- if (castType.isBaseType()) {
- return false;
- }
- if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
- if (expressionType.isCompatibleWith(castType))
- return true;
- else {
- if (castType.isCompatibleWith(expressionType)) {
- return true;
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+ if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
+ if (left.constant.booleanValue()) { // true == anything
+ // this is equivalent to the right argument inits
+ return right.analyseCode(currentScope, flowContext, flowInfo);
+ } else { // false == anything
+ // this is equivalent to the right argument inits negated
+ return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
}
- return false;
- }
- }
- if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass -------
- if (expressionType.isCompatibleWith(castType))
- return true;
- if (!((ReferenceBinding) expressionType).isFinal()) {
- return true;
}
- //no subclass for expressionTb, thus compile-time check is valid
- }
-
- return false;
- }
- if (expressionType.isInterface()) {
- if (castType.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
- if (expressionType.id == T_JavaLangCloneable || expressionType.id == T_JavaIoSerializable)
- //potential runtime error
- {
- return true;
+ if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
+ if (right.constant.booleanValue()) { // anything == true
+ // this is equivalent to the right argument inits
+ return left.analyseCode(currentScope, flowContext, flowInfo);
+ } else { // anything == false
+ // this is equivalent to the right argument inits negated
+ return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
+ }
}
- return false;
- }
- if (castType.isBaseType()) {
- return false;
- }
- if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
- if (castType.id == T_Object)
- return true;
- if (((ReferenceBinding) castType).isFinal()) { //no subclass for castTb, thus compile-time check is valid
- if (castType.isCompatibleWith(expressionType)) {
- return true;
+ return right.analyseCode(
+ currentScope, flowContext,
+ left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
+ } else { //NOT_EQUAL :
+ if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
+ if (!left.constant.booleanValue()) { // false != anything
+ // this is equivalent to the right argument inits
+ return right.analyseCode(currentScope, flowContext, flowInfo);
+ } else { // true != anything
+ // this is equivalent to the right argument inits negated
+ return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
}
- return false;
}
- return true;
- }
- if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface -------
- if (expressionType.isCompatibleWith(castType))
- return true;
- if (!castType.isCompatibleWith(expressionType)) {
- MethodBinding[] castTbMethods = ((ReferenceBinding) castType).methods();
- int castTbMethodsLength = castTbMethods.length;
- MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType).methods();
- int expressionTbMethodsLength = expressionTbMethods.length;
- for (int i = 0; i < castTbMethodsLength; i++) {
- for (int j = 0; j < expressionTbMethodsLength; j++) {
- if (CharOperation.equals(castTbMethods[i].selector, expressionTbMethods[j].selector)) {
- if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
- if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
- return false;
- }
- }
- }
- }
+ if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
+ if (!right.constant.booleanValue()) { // anything != false
+ // this is equivalent to the right argument inits
+ return left.analyseCode(currentScope, flowContext, flowInfo);
+ } else { // anything != true
+ // this is equivalent to the right argument inits negated
+ return left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
}
}
- return true;
+ return right.analyseCode(
+ currentScope, flowContext,
+ left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).asNegatedCondition().unconditionalInits();
}
- return false;
- }
- return false;
-}
-public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
- if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
- this.constant =
- Constant.computeConstantOperationEQUAL_EQUAL(
- left.constant,
- leftType.id,
- EQUAL_EQUAL,
- right.constant,
- rightType.id);
- if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
- constant = Constant.fromValue(!constant.booleanValue());
- } else {
- this.constant = NotAConstant;
- // no optimization for null == null
- }
-}
-/**
- * Normal == or != code generation.
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-
- if (constant != NotAConstant) {
- int pc = codeStream.position;
- if (valueRequired)
- codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- return;
}
- Label falseLabel;
- bits |= OnlyValueRequiredMASK;
- generateOptimizedBoolean(
- currentScope,
- codeStream,
- null,
- falseLabel = new Label(codeStream),
- valueRequired);
- if (falseLabel.hasForwardReferences()) {
- if (valueRequired){
- // comparison is TRUE
- codeStream.iconst_1();
- if ((bits & ValueForReturnMASK) != 0){
- codeStream.ireturn();
- // comparison is FALSE
- falseLabel.place();
- codeStream.iconst_0();
- } else {
- Label endLabel = new Label(codeStream);
- codeStream.goto_(endLabel);
- codeStream.decrStackSize(1);
- // comparison is FALSE
- falseLabel.place();
- codeStream.iconst_0();
- endLabel.place();
- }
+
+ public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
+ if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
+ this.constant =
+ Constant.computeConstantOperationEQUAL_EQUAL(
+ left.constant,
+ leftType.id,
+ right.constant,
+ rightType.id);
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
+ constant = Constant.fromValue(!constant.booleanValue());
} else {
- falseLabel.place();
- }
- }
-}
-/**
- * Boolean operator code generation
- * Optimized operations are: == and !=
- */
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
- if (constant != Constant.NotAConstant) {
- super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- return;
+ this.constant = NotAConstant;
+ // no optimization for null == null
+ }
}
- if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
- if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
- generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- } else {
- generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ /**
+ * Normal == or != code generation.
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+ if (constant != NotAConstant) {
+ int pc = codeStream.position;
+ if (valueRequired)
+ codeStream.generateConstant(constant, implicitConversion);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
}
- } else {
- if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
- generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
- } else {
- generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+ Label falseLabel;
+ bits |= OnlyValueRequiredMASK;
+ generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ falseLabel = new Label(codeStream),
+ valueRequired);
+ if (falseLabel.hasForwardReferences()) {
+ if (valueRequired){
+ // comparison is TRUE
+ codeStream.iconst_1();
+ if ((bits & ValueForReturnMASK) != 0){
+ codeStream.ireturn();
+ // comparison is FALSE
+ falseLabel.place();
+ codeStream.iconst_0();
+ } else {
+ Label endLabel = new Label(codeStream);
+ codeStream.goto_(endLabel);
+ codeStream.decrStackSize(1);
+ // comparison is FALSE
+ falseLabel.place();
+ codeStream.iconst_0();
+ endLabel.place();
+ }
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
+ falseLabel.place();
+ }
}
}
-}
-/**
- * Boolean generation for == with boolean operands
- *
- * Note this code does not optimize conditional constants !!!!
- */
-public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
- // optimized cases: true == x, false == x
- if (left.constant != NotAConstant) {
- boolean inline = left.constant.booleanValue();
- right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
- return;
- } // optimized cases: x == true, x == false
- if (right.constant != NotAConstant) {
- boolean inline = right.constant.booleanValue();
- left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
- return;
- }
- // default case
- left.generateCode(currentScope, codeStream, valueRequired);
- right.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- codeStream.if_icmpeq(trueLabel);
+ /**
+ * Boolean operator code generation
+ * Optimized operations are: == and !=
+ */
+ public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+ if (constant != Constant.NotAConstant) {
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ return;
+ }
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+ if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+ generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ } else {
+ generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
}
} else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.if_icmpne(falseLabel);
+ if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+ generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
} else {
- // no implicit fall through TRUE/FALSE --> should never occur
+ generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
}
}
}
- // reposition the endPC
- codeStream.updateLastRecordedEndPC(codeStream.position);
-}
-/**
- * Boolean generation for == with non-boolean operands
- *
- */
-public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
- int pc = codeStream.position;
- Constant inline;
- if ((inline = right.constant) != NotAConstant) {
- // optimized case: x == 0
- if (((left.implicitConversion >> 4) == T_int) && (inline.intValue() == 0)) {
- left.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- codeStream.ifeq(trueLabel);
- }
+ /**
+ * Boolean generation for == with boolean operands
+ *
+ * Note this code does not optimize conditional constants !!!!
+ */
+ public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+ // optimized cases: true == x, false == x
+ if (left.constant != NotAConstant) {
+ boolean inline = left.constant.booleanValue();
+ right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
+ return;
+ } // optimized cases: x == true, x == false
+ if (right.constant != NotAConstant) {
+ boolean inline = right.constant.booleanValue();
+ left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
+ return;
+ }
+ // default case
+ left.generateCode(currentScope, codeStream, valueRequired);
+ right.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ codeStream.if_icmpeq(trueLabel);
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ codeStream.if_icmpne(falseLabel);
} else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.ifne(falseLabel);
- } else {
- // no implicit fall through TRUE/FALSE --> should never occur
- }
+ // no implicit fall through TRUE/FALSE --> should never occur
}
}
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- return;
}
+ // reposition the endPC
+ codeStream.updateLastRecordedEndPC(codeStream.position);
}
- if ((inline = left.constant) != NotAConstant) {
- // optimized case: 0 == x
- if (((left.implicitConversion >> 4) == T_int)
- && (inline.intValue() == 0)) {
- right.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- codeStream.ifeq(trueLabel);
+ /**
+ * Boolean generation for == with non-boolean operands
+ *
+ */
+ public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+ int pc = codeStream.position;
+ Constant inline;
+ if ((inline = right.constant) != NotAConstant) {
+ // optimized case: x == 0
+ if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) {
+ left.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ codeStream.ifeq(trueLabel);
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ codeStream.ifne(falseLabel);
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
}
- } else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.ifne(falseLabel);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ }
+ if ((inline = left.constant) != NotAConstant) {
+ // optimized case: 0 == x
+ if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
+ && (inline.intValue() == 0)) {
+ right.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ codeStream.ifeq(trueLabel);
+ }
} else {
- // no implicit fall through TRUE/FALSE --> should never occur
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ codeStream.ifne(falseLabel);
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
}
}
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
}
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- return;
}
- }
- // null cases
- // optimized case: x == null
- if (right instanceof NullLiteral) {
- if (left instanceof NullLiteral) {
- // null == null
- if (valueRequired) {
- if ((bits & OnlyValueRequiredMASK) != 0) {
- if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
- codeStream.iconst_1();
+ // null cases
+ // optimized case: x == null
+ if (right instanceof NullLiteral) {
+ if (left instanceof NullLiteral) {
+ // null == null
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+ codeStream.iconst_1();
+ } else {
+ codeStream.iconst_0();
+ }
} else {
- codeStream.iconst_0();
+ if (falseLabel == null) {
+ // implicit falling through the FALSE case
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ }
+ } else {
+ left.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ codeStream.ifnull(trueLabel);
}
} else {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ codeStream.ifnonnull(falseLabel);
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
}
+ }
}
}
- } else {
- left.generateCode(currentScope, codeStream, valueRequired);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ } else if (left instanceof NullLiteral) { // optimized case: null == x
+ right.generateCode(currentScope, codeStream, valueRequired);
if (valueRequired) {
if (falseLabel == null) {
if (trueLabel != null) {
@@ -414,165 +340,162 @@ public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream
}
}
}
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
}
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- return;
- } else if (left instanceof NullLiteral) { // optimized case: null == x
+
+ // default case
+ left.generateCode(currentScope, codeStream, valueRequired);
right.generateCode(currentScope, codeStream, valueRequired);
if (valueRequired) {
if (falseLabel == null) {
if (trueLabel != null) {
// implicit falling through the FALSE case
- codeStream.ifnull(trueLabel);
+ switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
+ case T_int :
+ codeStream.if_icmpeq(trueLabel);
+ break;
+ case T_float :
+ codeStream.fcmpl();
+ codeStream.ifeq(trueLabel);
+ break;
+ case T_long :
+ codeStream.lcmp();
+ codeStream.ifeq(trueLabel);
+ break;
+ case T_double :
+ codeStream.dcmpl();
+ codeStream.ifeq(trueLabel);
+ break;
+ default :
+ codeStream.if_acmpeq(trueLabel);
+ }
}
} else {
// implicit falling through the TRUE case
if (trueLabel == null) {
- codeStream.ifnonnull(falseLabel);
+ switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
+ case T_int :
+ codeStream.if_icmpne(falseLabel);
+ break;
+ case T_float :
+ codeStream.fcmpl();
+ codeStream.ifne(falseLabel);
+ break;
+ case T_long :
+ codeStream.lcmp();
+ codeStream.ifne(falseLabel);
+ break;
+ case T_double :
+ codeStream.dcmpl();
+ codeStream.ifne(falseLabel);
+ break;
+ default :
+ codeStream.if_acmpne(falseLabel);
+ }
} else {
// no implicit fall through TRUE/FALSE --> should never occur
}
}
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
- return;
}
-
- // default case
- left.generateCode(currentScope, codeStream, valueRequired);
- right.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- switch (left.implicitConversion >> 4) { // operand runtime type
- case T_int :
- codeStream.if_icmpeq(trueLabel);
- break;
- case T_float :
- codeStream.fcmpl();
- codeStream.ifeq(trueLabel);
- break;
- case T_long :
- codeStream.lcmp();
- codeStream.ifeq(trueLabel);
- break;
- case T_double :
- codeStream.dcmpl();
- codeStream.ifeq(trueLabel);
- break;
- default :
- codeStream.if_acmpeq(trueLabel);
- }
- }
- } else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- switch (left.implicitConversion >> 4) { // operand runtime type
- case T_int :
- codeStream.if_icmpne(falseLabel);
- break;
- case T_float :
- codeStream.fcmpl();
- codeStream.ifne(falseLabel);
- break;
- case T_long :
- codeStream.lcmp();
- codeStream.ifne(falseLabel);
- break;
- case T_double :
- codeStream.dcmpl();
- codeStream.ifne(falseLabel);
- break;
- default :
- codeStream.if_acmpne(falseLabel);
- }
- } else {
- // no implicit fall through TRUE/FALSE --> should never occur
- }
- }
- }
- codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public boolean isCompactableOperation() {
- return false;
-}
-public TypeBinding resolveType(BlockScope scope) {
-
- boolean leftIsCast, rightIsCast;
- if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
- TypeBinding leftType = left.resolveType(scope);
-
- if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
- TypeBinding rightType = right.resolveType(scope);
-
- // always return BooleanBinding
- if (leftType == null || rightType == null){
- constant = NotAConstant;
- return null;
+ public boolean isCompactableOperation() {
+ return false;
}
-
- // both base type
- if (leftType.isBaseType() && rightType.isBaseType()) {
- // the code is an int
- // (cast) left == (cast) right --> result
- // 0000 0000 0000 0000 0000
- // <<16 <<12 <<8 <<4 <<0
- int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftType.id << 4) + rightType.id];
- left.implicitConversion = operatorSignature >>> 12;
- right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
- bits |= operatorSignature & 0xF;
- if ((operatorSignature & 0x0000F) == T_undefined) {
- constant = Constant.NotAConstant;
- scope.problemReporter().invalidOperator(this, leftType, rightType);
+ public TypeBinding resolveType(BlockScope scope) {
+
+ boolean leftIsCast, rightIsCast;
+ if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+ TypeBinding originalLeftType = left.resolveType(scope);
+
+ if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+ TypeBinding originalRightType = right.resolveType(scope);
+
+ // always return BooleanBinding
+ if (originalLeftType == null || originalRightType == null){
+ constant = NotAConstant;
return null;
}
- // check need for operand cast
- if (leftIsCast || rightIsCast) {
- CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
+
+ // autoboxing support
+ LookupEnvironment env = scope.environment();
+ boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+ TypeBinding leftType = originalLeftType, rightType = originalRightType;
+ if (use15specifics) {
+ if (leftType != NullBinding && leftType.isBaseType()) {
+ if (!rightType.isBaseType()) {
+ rightType = env.computeBoxingType(rightType);
+ }
+ } else {
+ if (rightType != NullBinding && rightType.isBaseType()) {
+ leftType = env.computeBoxingType(leftType);
+ }
+ }
}
- computeConstant(leftType, rightType);
- return this.resolvedType = BooleanBinding;
- }
-
- // Object references
- // spec 15.20.3
- if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) {
- // (special case for String)
- if ((rightType.id == T_String) && (leftType.id == T_String)) {
+ // both base type
+ if (leftType.isBaseType() && rightType.isBaseType()) {
+ int leftTypeID = leftType.id;
+ int rightTypeID = rightType.id;
+
+ // the code is an int
+ // (cast) left == (cast) right --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+ int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftTypeID << 4) + rightTypeID];
+ left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), originalLeftType);
+ right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), originalRightType);
+ bits |= operatorSignature & 0xF;
+ if ((operatorSignature & 0x0000F) == T_undefined) {
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftType, rightType);
+ return null;
+ }
+ // check need for operand cast
+ if (leftIsCast || rightIsCast) {
+ CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
+ }
computeConstant(leftType, rightType);
- } else {
- constant = NotAConstant;
- }
- if (rightType.id == T_String) {
- right.implicitConversion = String2String;
- }
- if (leftType.id == T_String) {
- left.implicitConversion = String2String;
+ return this.resolvedType = BooleanBinding;
}
- // check need for operand cast
- boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
- boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
- if (unnecessaryLeftCast || unnecessaryRightCast) {
- TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
- TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
- if (areTypesCastCompatible(scope, alternateLeftType, alternateRightType)
- || areTypesCastCompatible(scope, alternateRightType, alternateLeftType)) {
- if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left);
- if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+
+ // Object references
+ // spec 15.20.3
+ if (this.checkCastTypesCompatibility(scope, leftType, rightType, null)
+ || this.checkCastTypesCompatibility(scope, rightType, leftType, null)) {
+
+ // (special case for String)
+ if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) {
+ computeConstant(leftType, rightType);
+ } else {
+ constant = NotAConstant;
}
+ TypeBinding objectType = scope.getJavaLangObject();
+ left.computeConversion(scope, objectType, leftType);
+ right.computeConversion(scope, objectType, rightType);
+ // check need for operand cast
+ boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
+ boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
+ if (unnecessaryLeftCast || unnecessaryRightCast) {
+ TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
+ TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
+ if (this.checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null)
+ || this.checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) {
+ if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left);
+ if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+ }
+ }
+ return this.resolvedType = BooleanBinding;
}
- return this.resolvedType = BooleanBinding;
+ constant = NotAConstant;
+ scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
+ return null;
}
- constant = NotAConstant;
- scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
- return null;
-}
-public void traverse(ASTVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- left.traverse(visitor, scope);
- right.traverse(visitor, scope);
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
}
- visitor.endVisit(this, scope);
-}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/src/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index ec709ff..a0b814e 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -15,24 +15,26 @@ import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
-public class ExplicitConstructorCall
- extends Statement
- implements InvocationSite {
+public class ExplicitConstructorCall extends Statement implements InvocationSite {
public Expression[] arguments;
public Expression qualification;
- public MethodBinding binding;
-
+ public MethodBinding binding; // exact binding resulting from lookup
+ protected MethodBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
+ MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation
public int accessMode;
-
+ public TypeReference[] typeArguments;
+ public TypeBinding[] genericTypeArguments;
+
public final static int ImplicitSuper = 1;
public final static int Super = 2;
public final static int This = 3;
public VariableBinding[][] implicitArguments;
boolean discardEnclosingInstance;
-
- MethodBinding syntheticAccessor;
+
+ // TODO Remove once DOMParser is activated
+ public int typeArgumentsSourceStart;
public ExplicitConstructorCall(int accessMode) {
this.accessMode = accessMode;
@@ -101,8 +103,14 @@ public class ExplicitConstructorCall
int pc = codeStream.position;
codeStream.aload_0();
+ ReferenceBinding targetType = this.codegenBinding.declaringClass;
+
+ // special name&ordinal argument generation for enum constructors
+ if (targetType.erasure().id == T_JavaLangEnum || targetType.isEnum()) {
+ codeStream.aload_1(); // pass along name param as name arg
+ codeStream.iload_2(); // pass along ordinal param as ordinal arg
+ }
// handling innerclass constructor invocation
- ReferenceBinding targetType = binding.declaringClass;
// handling innerclass instance allocation - enclosing instance arguments
if (targetType.isNestedType()) {
codeStream.generateSyntheticEnclosingInstanceValues(
@@ -111,12 +119,9 @@ public class ExplicitConstructorCall
discardEnclosingInstance ? null : qualification,
this);
}
- // regular code gen
- if (arguments != null) {
- for (int i = 0, max = arguments.length; i < max; i++) {
- arguments[i].generateCode(currentScope, codeStream, true);
- }
- }
+ // generate arguments
+ generateArguments(binding, arguments, currentScope, codeStream);
+
// handling innerclass instance allocation - outer local arguments
if (targetType.isNestedType()) {
codeStream.generateSyntheticOuterArgumentValues(
@@ -127,21 +132,26 @@ public class ExplicitConstructorCall
if (syntheticAccessor != null) {
// synthetic accessor got some extra arguments appended to its signature, which need values
for (int i = 0,
- max = syntheticAccessor.parameters.length - binding.parameters.length;
+ max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
i < max;
i++) {
codeStream.aconst_null();
}
codeStream.invokespecial(syntheticAccessor);
} else {
- codeStream.invokespecial(binding);
+ codeStream.invokespecial(this.codegenBinding);
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
} finally {
((MethodScope) currentScope).isConstructorCall = false;
}
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return this.genericTypeArguments;
+ }
public boolean isImplicitSuper() {
//return true if I'm of these compiler added statement super();
@@ -166,18 +176,18 @@ public class ExplicitConstructorCall
* exact need.
*/
void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
- ReferenceBinding superType;
+ ReferenceBinding superTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
if (!flowInfo.isReachable()) return;
// perform some emulation work in case there is some and we are inside a local type only
- if ((superType = binding.declaringClass).isNestedType()
+ if (superTypeErasure.isNestedType()
&& currentScope.enclosingSourceType().isLocalType()) {
- if (superType.isLocalType()) {
- ((LocalTypeBinding) superType).addInnerEmulationDependent(currentScope, qualification != null);
+ if (superTypeErasure.isLocalType()) {
+ ((LocalTypeBinding) superTypeErasure).addInnerEmulationDependent(currentScope, qualification != null);
} else {
// locally propagate, since we already now the desired shape for sure
- currentScope.propagateInnerEmulation(superType, qualification != null);
+ currentScope.propagateInnerEmulation(superTypeErasure, qualification != null);
}
}
}
@@ -185,19 +195,19 @@ public class ExplicitConstructorCall
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
if (!flowInfo.isReachable()) return;
+ // if constructor from parameterized type got found, use the original constructor at codegen time
+ this.codegenBinding = this.binding.original();
+
// perform some emulation work in case there is some and we are inside a local type only
- if (binding.isPrivate() && (accessMode != This)) {
+ if (binding.isPrivate() && accessMode != This) {
- if (currentScope
- .environment()
- .options
- .isPrivateConstructorAccessChangingVisibility) {
- binding.tagForClearingPrivateModifier();
+ if (currentScope.environment().options.isPrivateConstructorAccessChangingVisibility) {
+ this.codegenBinding.tagForClearingPrivateModifier();
// constructor will not be dumped as private, no emulation required thus
} else {
syntheticAccessor =
- ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ ((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+ currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
}
}
}
@@ -206,6 +216,16 @@ public class ExplicitConstructorCall
printIndent(indent, output);
if (qualification != null) qualification.printExpression(0, output).append('.');
+ if (typeArguments != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeArguments.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeArguments[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArguments[max].print(0, output);
+ output.append('>');
+ }
if (accessMode == This) {
output.append("this("); //$NON-NLS-1$
} else {
@@ -243,7 +263,10 @@ public class ExplicitConstructorCall
if (receiverType == null) {
return;
}
-
+ // prevent (explicit) super constructor invocation from within enum
+ if (this.accessMode == Super && receiverType.erasure().id == T_JavaLangEnum) {
+ scope.problemReporter().cannotInvokeSuperConstructorInEnum(this, methodScope.referenceMethod().binding);
+ }
// qualification should be from the type of the enclosingType
if (qualification != null) {
if (accessMode != Super) {
@@ -259,10 +282,24 @@ public class ExplicitConstructorCall
discardEnclosingInstance = true;
} else {
TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
- qualification.implicitWidening(qTb, qTb);
+ qualification.computeConversion(scope, qTb, qTb);
}
}
-
+ // resolve type arguments (for generic constructor call)
+ if (this.typeArguments != null) {
+ int length = this.typeArguments.length;
+ boolean argHasError = false; // typeChecks all arguments
+ this.genericTypeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+ argHasError = true;
+ }
+ }
+ if (argHasError) {
+ return;
+ }
+ }
+
// arguments buffering for the method lookup
TypeBinding[] argumentTypes = NoParameters;
boolean argsContainCast = false;
@@ -283,24 +320,17 @@ public class ExplicitConstructorCall
if (argHasError) {
return;
}
+ } else if (receiverType.erasure().id == T_JavaLangEnum) {
+ // TODO (philippe) get rid of once well-known binding is available
+ argumentTypes = new TypeBinding[] { scope.getJavaLangString(), BaseTypes.IntBinding };
}
if ((binding = scope.getConstructor(receiverType, argumentTypes, this)).isValidBinding()) {
if (isMethodUseDeprecated(binding, scope))
scope.problemReporter().deprecatedMethod(binding, this);
-
- // see for user-implicit widening conversion
- if (arguments != null) {
- int length = arguments.length;
- TypeBinding[] paramTypes = binding.parameters;
- for (int i = 0; i < length; i++) {
- arguments[i].implicitWidening(paramTypes[i], argumentTypes[i]);
- }
- if (argsContainCast) {
- CastExpression.checkNeedForArgumentCasts(scope, null, receiverType, binding, this.arguments, argumentTypes, this);
- }
- }
+ if (this.arguments != null)
+ checkInvocationArguments(scope, null, receiverType, binding, this.arguments, argumentTypes, argsContainCast, this);
if (binding.isPrivate()) {
- binding.modifiers |= AccPrivateUsed;
+ binding.original().modifiers |= AccPrivateUsed;
}
} else {
if (binding.declaringClass == null)
@@ -330,6 +360,11 @@ public class ExplicitConstructorCall
if (this.qualification != null) {
this.qualification.traverse(visitor, scope);
}
+ if (this.typeArguments != null) {
+ for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+ this.typeArguments[i].traverse(visitor, scope);
+ }
+ }
if (this.arguments != null) {
for (int i = 0, argumentLength = this.arguments.length; i < argumentLength; i++)
this.arguments[i].traverse(visitor, scope);
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Expression.java b/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
index ae3b502..df2538d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -10,6 +10,10 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import java.util.ArrayList;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
@@ -19,41 +23,6 @@ import org.eclipse.jdt.internal.compiler.util.Util;
public abstract class Expression extends Statement {
- //Some expression may not be used - from a java semantic point
- //of view only - as statements. Other may. In order to avoid the creation
- //of wrappers around expression in order to tune them as expression
- //Expression is a subclass of Statement. See the message isValidJavaStatement()
-
- public int implicitConversion;
- public TypeBinding resolvedType;
-
- public Constant constant;
-
- public Expression() {
- super();
- }
-
- public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-
- return flowInfo;
- }
-
- public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
-
- return analyseCode(currentScope, flowContext, flowInfo);
- }
-
- /**
- * Constant usable for bytecode pattern optimizations, but cannot be inlined
- * since it is not strictly equivalent to the definition of constant expressions.
- * In particular, some side-effects may be required to occur (only the end value
- * is known).
- * @return Constant known to be of boolean type
- */
- public Constant optimizedBooleanConstant() {
- return this.constant;
- }
-
public static final boolean isConstantValueRepresentable(
Constant constant,
int constantTypeID,
@@ -208,7 +177,345 @@ public abstract class Expression extends Statement {
return false; //boolean
}
}
+
+ public Constant constant;
+
+ //Some expression may not be used - from a java semantic point
+ //of view only - as statements. Other may. In order to avoid the creation
+ //of wrappers around expression in order to tune them as expression
+ //Expression is a subclass of Statement. See the message isValidJavaStatement()
+
+ public int implicitConversion;
+ public TypeBinding resolvedType;
+
+ public Expression() {
+ super();
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+ return flowInfo;
+ }
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
+
+ return analyseCode(currentScope, flowContext, flowInfo);
+ }
+
+ /**
+ * Returns false if cast is not legal.
+ */
+ public final boolean checkCastTypesCompatibility(
+ Scope scope,
+ TypeBinding castType,
+ TypeBinding expressionType,
+ Expression expression) {
+
+ // see specifications 5.5
+ // handle errors and process constant when needed
+
+ // if either one of the type is null ==>
+ // some error has been already reported some where ==>
+ // we then do not report an obvious-cascade-error.
+
+ if (castType == null || expressionType == null) return true;
+
+ // identity conversion cannot be performed upfront, due to side-effects
+ // like constant propagation
+ LookupEnvironment env = scope.environment();
+ boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+ if (castType.isBaseType()) {
+ if (expressionType.isBaseType()) {
+ if (expressionType == castType) {
+ if (expression != null) {
+ this.constant = expression.constant; //use the same constant
+ }
+ tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ boolean necessary = false;
+ if (expressionType.isCompatibleWith(castType)
+ || (necessary = BaseTypeBinding.isNarrowing(castType.id, expressionType.id))) {
+ if (expression != null) {
+ expression.implicitConversion = (castType.id << 4) + expressionType.id;
+ if (expression.constant != Constant.NotAConstant) {
+ constant = expression.constant.castTo(expression.implicitConversion);
+ }
+ }
+ if (!necessary) tagAsUnnecessaryCast(scope, castType);
+ return true;
+
+ }
+ } else if (use15specifics) { // unboxing - only exact match is allowed
+ if (env.computeBoxingType(expressionType) == castType) {
+ // TODO (philippe) could tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ }
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ } else if (use15specifics && expressionType.isBaseType()) { // boxing - only exact match is allowed
+ if (env.computeBoxingType(castType) == expressionType) {
+ // TODO (philippe) could tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ }
+
+ //-----------cast to something which is NOT a base type--------------------------
+ if (expressionType == NullBinding) {
+ tagAsUnnecessaryCast(scope, castType);
+ return true; //null is compatible with every thing
+ }
+ if (expressionType.isBaseType()) {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+
+ if (expressionType.isArrayType()) {
+ if (castType == expressionType) {
+ tagAsUnnecessaryCast(scope, castType);
+ return true; // identity conversion
+ }
+
+ if (castType.isArrayType()) {
+ //------- (castType.isArray) expressionType.isArray -----------
+ TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType();
+ if (exprElementType.isBaseType()) {
+ // <---stop the recursion-------
+ if (((ArrayBinding) castType).elementsType() == exprElementType) {
+ tagAsNeedCheckCast();
+ return true;
+ } else {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+ }
+ // recursively on the elements...
+ return checkCastTypesCompatibility(
+ scope,
+ ((ArrayBinding) castType).elementsType(),
+ exprElementType,
+ expression);
+ } else if (
+ castType.isClass()) {
+ //------(castType.isClass) expressionType.isArray ---------------
+ if (castType.id == T_JavaLangObject) {
+ tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ } else { //------- (castType.isInterface) expressionType.isArray -----------
+ if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
+ tagAsNeedCheckCast();
+ return true;
+ }
+ }
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+
+ if (expressionType.isClass()) {
+ if (castType.isArrayType()) {
+ // ---- (castType.isArray) expressionType.isClass -------
+ if (expressionType.id == T_JavaLangObject) { // potential runtime error
+ tagAsNeedCheckCast();
+ return true;
+ }
+ } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
+
+ ReferenceBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+ if (match != null) {
+ if (expression != null && castType.id == T_JavaLangString) this.constant = expression.constant; // (String) cst is still a constant
+ return checkUnsafeCast(scope, castType, expressionType, match, false);
+ }
+ match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+ if (match != null) {
+ tagAsNeedCheckCast();
+ return checkUnsafeCast(scope, castType, expressionType, match, true);
+ }
+ } else { // ----- (castType.isInterface) expressionType.isClass -------
+
+ ReferenceBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+ if (match != null) {
+ return checkUnsafeCast(scope, castType, expressionType, match, false);
+ }
+ // a subclass may implement the interface ==> no check at compile time
+ if (!((ReferenceBinding) expressionType).isFinal()) {
+ tagAsNeedCheckCast();
+ match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+ if (match != null) {
+ return checkUnsafeCast(scope, castType, expressionType, match, true);
+ }
+ return true;
+ }
+ // no subclass for expressionType, thus compile-time check is valid
+ }
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+
+ // if (expressionType.isInterface()) { cannot be anything else
+ if (castType.isArrayType()) {
+ // ----- (castType.isArray) expressionType.isInterface ------
+ if (expressionType.id == T_JavaLangCloneable
+ || expressionType.id == T_JavaIoSerializable) {// potential runtime error
+ tagAsNeedCheckCast();
+ return true;
+ } else {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+ } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
+
+ if (castType.id == T_JavaLangObject) { // no runtime error
+ tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ if (((ReferenceBinding) castType).isFinal()) {
+ // no subclass for castType, thus compile-time check is valid
+ ReferenceBinding match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+ if (match == null) {
+ // potential runtime error
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+ }
+ } else { // ----- (castType.isInterface) expressionType.isInterface -------
+
+ ReferenceBinding match = ((ReferenceBinding)expressionType).findSuperTypeErasingTo((ReferenceBinding)castType.erasure());
+ if (match != null) {
+ return checkUnsafeCast(scope, castType, expressionType, match, false);
+ }
+
+ match = ((ReferenceBinding)castType).findSuperTypeErasingTo((ReferenceBinding)expressionType.erasure());
+ if (match != null) {
+ tagAsNeedCheckCast();
+ return checkUnsafeCast(scope, castType, expressionType, match, true);
+ } else {
+ MethodBinding[] castTypeMethods = getAllInheritedMethods((ReferenceBinding) castType);
+ MethodBinding[] expressionTypeMethods =
+ getAllInheritedMethods((ReferenceBinding) expressionType);
+ int exprMethodsLength = expressionTypeMethods.length;
+ for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++) {
+ for (int j = 0; j < exprMethodsLength; j++) {
+ if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
+ && (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
+ && castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+
+ }
+ }
+ }
+ }
+ }
+ tagAsNeedCheckCast();
+ return true;
+ }
+
+ public FlowInfo checkNullStatus(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int nullStatus) {
+
+ LocalVariableBinding local = this.localVariableBinding();
+ if (local != null) {
+ switch(nullStatus) {
+ case FlowInfo.NULL :
+ flowContext.recordUsingNullReference(scope, local, this, FlowInfo.NULL, flowInfo);
+ flowInfo.markAsDefinitelyNull(local); // from thereon it is set
+ break;
+ case FlowInfo.NON_NULL :
+ flowContext.recordUsingNullReference(scope, local, this, FlowInfo.NON_NULL, flowInfo);
+ flowInfo.markAsDefinitelyNonNull(local); // from thereon it is set
+ break;
+ case FlowInfo.UNKNOWN :
+ break;
+ }
+ }
+ return flowInfo;
+ }
+
+ private MethodBinding[] getAllInheritedMethods(ReferenceBinding binding) {
+ ArrayList collector = new ArrayList();
+ getAllInheritedMethods0(binding, collector);
+ return (MethodBinding[]) collector.toArray(new MethodBinding[collector.size()]);
+ }
+
+ private void getAllInheritedMethods0(ReferenceBinding binding, ArrayList collector) {
+ if (!binding.isInterface()) return;
+ MethodBinding[] methodBindings = binding.methods();
+ for (int i = 0, max = methodBindings.length; i < max; i++) {
+ collector.add(methodBindings[i]);
+ }
+ ReferenceBinding[] superInterfaces = binding.superInterfaces();
+ for (int i = 0, max = superInterfaces.length; i < max; i++) {
+ getAllInheritedMethods0(superInterfaces[i], collector);
+ }
+ }
+ public void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {
+ // do nothing by default - see EqualExpression
+ }
+
+ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ if (match == castType) {
+ if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+ if (castType.isBoundParameterizedType() || castType.isGenericType()) {
+ if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
+ reportIllegalCast(scope, castType, expressionType);
+ return false;
+ }
+ }
+ if (!isNarrowing) tagAsUnnecessaryCast(scope, castType);
+ return true;
+ }
+
+ /**
+ * Base types need that the widening is explicitly done by the compiler using some bytecode like i2f.
+ * Also check unsafe type operations.
+ */
+ public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+ if (runtimeTimeType == null || compileTimeType == null)
+ return;
+ if (this.implicitConversion != 0) return; // already set independantly
+
+ // it is possible for a Byte to be unboxed to a byte & then converted to an int
+ // but it is not possible for a byte to become Byte & then assigned to an Integer,
+ // or to become an int before boxed into an Integer
+ if (runtimeTimeType != NullBinding && runtimeTimeType.isBaseType()) {
+ if (!compileTimeType.isBaseType()) {
+ compileTimeType = scope.environment().computeBoxingType(compileTimeType);
+ this.implicitConversion = UNBOXING;
+ }
+ } else {
+ if (compileTimeType != NullBinding && compileTimeType.isBaseType()) {
+ TypeBinding boxedType = scope.environment().computeBoxingType(runtimeTimeType);
+ if (boxedType == runtimeTimeType) // Object o = 12;
+ boxedType = compileTimeType;
+ this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id;
+ return;
+ }
+ }
+
+ switch (runtimeTimeType.id) {
+ case T_byte :
+ case T_short :
+ case T_char :
+ this.implicitConversion |= (T_int << 4) + compileTimeType.id;
+ break;
+ case T_JavaLangString :
+ case T_float :
+ case T_boolean :
+ case T_double :
+ case T_int : //implicitConversion may result in i2i which will result in NO code gen
+ case T_long :
+ this.implicitConversion |= (runtimeTimeType.id << 4) + compileTimeType.id;
+ break;
+ default : // regular object ref
+// if (compileTimeType.isRawType() && runtimeTimeType.isBoundParameterizedType()) {
+// scope.problemReporter().unsafeRawExpression(this, compileTimeType, runtimeTimeType);
+// }
+ }
+ }
/**
* Expression statements are plain expressions, however they generate like
* normal expressions with no value required.
@@ -317,93 +624,58 @@ public abstract class Expression extends Statement {
* creation, further operands should rather be only appended to the current one.
* By default: no optimization.
*/
- public void generateOptimizedStringBuffer(
+ public void generateOptimizedStringConcatenation(
BlockScope blockScope,
- org.eclipse.jdt.internal.compiler.codegen.CodeStream codeStream,
+ CodeStream codeStream,
int typeID) {
- if (typeID == T_String && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
+ if (typeID == T_JavaLangString && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
return; // optimize str + ""
}
generateCode(blockScope, codeStream, true);
- codeStream.invokeStringBufferAppendForType(typeID);
+ codeStream.invokeStringConcatenationAppendForType(typeID);
}
/* Optimized (java) code generation for string concatenations that involve StringBuffer
* creation: going through this path means that there is no need for a new StringBuffer
* creation, further operands should rather be only appended to the current one.
*/
- public void generateOptimizedStringBufferCreation(
+ public void generateOptimizedStringConcatenationCreation(
BlockScope blockScope,
CodeStream codeStream,
int typeID) {
- // Optimization only for integers and strings
- if (typeID == T_Object) {
- // in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object)
- // append(Object) returns append(valueOf(Object)), which means that the null case is handled by append(String).
- codeStream.newStringBuffer();
- codeStream.dup();
- codeStream.invokeStringBufferDefaultConstructor();
- generateCode(blockScope, codeStream, true);
- codeStream.invokeStringBufferAppendForType(T_Object);
- return;
- }
- codeStream.newStringBuffer();
+ codeStream.newStringContatenation();
codeStream.dup();
- if (typeID == T_String || typeID == T_null) {
- if (constant != NotAConstant) {
- String stringValue = constant.stringValue();
- if (stringValue.length() == 0) { // optimize ""+
- codeStream.invokeStringBufferDefaultConstructor();
- return;
- }
- codeStream.ldc(stringValue);
- } else {
+ switch (typeID) {
+ case T_JavaLangObject :
+ case T_undefined :
+ // in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object)
+ // append(Object) returns append(valueOf(Object)), which means that the null case is handled by the next case.
+ codeStream.invokeStringConcatenationDefaultConstructor();
generateCode(blockScope, codeStream, true);
- codeStream.invokeStringValueOf(T_Object);
- }
- } else {
- generateCode(blockScope, codeStream, true);
- codeStream.invokeStringValueOf(typeID);
- }
- codeStream.invokeStringBufferStringConstructor();
- }
-
- // Base types need that the widening is explicitly done by the compiler using some bytecode like i2f
- public void implicitWidening(
- TypeBinding runtimeTimeType,
- TypeBinding compileTimeType) {
-
- if (runtimeTimeType == null || compileTimeType == null)
- return;
-
-// if (compileTimeType.id == T_null) {
-// // this case is possible only for constant null
-// // The type of runtime is a reference type
-// // The code gen use the constant id thus any value
-// // for the runtime id (akak the <<4) could be used.
-// // T_Object is used as some general T_reference
-// implicitConversion = (T_Object << 4) + T_null;
-// return;
-// }
-
- switch (runtimeTimeType.id) {
- case T_byte :
- case T_short :
- case T_char :
- implicitConversion = (T_int << 4) + compileTimeType.id;
- break;
- case T_String :
- case T_float :
- case T_boolean :
- case T_double :
- case T_int : //implicitConversion may result in i2i which will result in NO code gen
- case T_long :
- implicitConversion = (runtimeTimeType.id << 4) + compileTimeType.id;
+ codeStream.invokeStringConcatenationAppendForType(T_JavaLangObject);
+ return;
+ case T_JavaLangString :
+ case T_null :
+ if (constant != NotAConstant) {
+ String stringValue = constant.stringValue();
+ if (stringValue.length() == 0) { // optimize ""+
+ codeStream.invokeStringConcatenationDefaultConstructor();
+ return;
+ }
+ codeStream.ldc(stringValue);
+ } else {
+ // null case is not a constant
+ generateCode(blockScope, codeStream, true);
+ codeStream.invokeStringValueOf(T_JavaLangObject);
+ }
break;
- default : //nothing on regular object ref
+ default :
+ generateCode(blockScope, codeStream, true);
+ codeStream.invokeStringValueOf(typeID);
}
+ codeStream.invokeStringConcatenationStringConstructor();
}
public boolean isCompactableOperation() {
@@ -413,11 +685,9 @@ public abstract class Expression extends Statement {
//Return true if the conversion is done AUTOMATICALLY by the vm
//while the javaVM is an int based-machine, thus for example pushing
- //a byte onto the stack , will automatically creates a int on the stack
+ //a byte onto the stack , will automatically create an int on the stack
//(this request some work d be done by the VM on signed numbers)
- public boolean isConstantValueOfTypeAssignableToType(
- TypeBinding constantType,
- TypeBinding targetType) {
+ public boolean isConstantValueOfTypeAssignableToType(TypeBinding constantType, TypeBinding targetType) {
if (constant == Constant.NotAConstant)
return false;
@@ -438,7 +708,49 @@ public abstract class Expression extends Statement {
public boolean isTypeReference() {
return false;
}
+
+ public int nullStatus(FlowInfo flowInfo) {
+
+ if (this.constant != null && this.constant != NotAConstant)
+ return FlowInfo.NON_NULL; // constant expression cannot be null
+
+ LocalVariableBinding local = localVariableBinding();
+ if (local != null) {
+ if (flowInfo.isDefinitelyNull(local))
+ return FlowInfo.NULL;
+ if (flowInfo.isDefinitelyNonNull(local))
+ return FlowInfo.NON_NULL;
+ return FlowInfo.UNKNOWN;
+ }
+ return FlowInfo.NON_NULL;
+ }
+
+ /**
+ * Constant usable for bytecode pattern optimizations, but cannot be inlined
+ * since it is not strictly equivalent to the definition of constant expressions.
+ * In particular, some side-effects may be required to occur (only the end value
+ * is known).
+ * @return Constant known to be of boolean type
+ */
+ public Constant optimizedBooleanConstant() {
+ return this.constant;
+ }
+
+ public StringBuffer print(int indent, StringBuffer output) {
+ printIndent(indent, output);
+ return printExpression(indent, output);
+ }
+ public abstract StringBuffer printExpression(int indent, StringBuffer output);
+
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ return print(indent, output).append(";"); //$NON-NLS-1$
+ }
+
+ public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+ // do nothing by default
+ }
+
public void resolve(BlockScope scope) {
// drops the returning expression's type whatever the type is.
@@ -461,28 +773,39 @@ public abstract class Expression extends Statement {
BlockScope scope,
TypeBinding expectedType) {
+ this.setExpectedType(expectedType); // needed in case of generic method invocation
TypeBinding expressionType = this.resolveType(scope);
if (expressionType == null) return null;
if (expressionType == expectedType) return expressionType;
if (!expressionType.isCompatibleWith(expectedType)) {
- scope.problemReporter().typeMismatchError(expressionType, expectedType, this);
- return null;
+ if (scope.isBoxingCompatibleWith(expressionType, expectedType)) {
+ this.computeConversion(scope, expectedType, expressionType);
+ } else {
+ scope.problemReporter().typeMismatchError(expressionType, expectedType, this);
+ return null;
+ }
}
return expressionType;
}
- public StringBuffer print(int indent, StringBuffer output) {
- printIndent(indent, output);
- return printExpression(indent, output);
+ /**
+ * Record the type expectation before this expression is typechecked.
+ * e.g. String s = foo();, foo() will be tagged as being expected of type String
+ * Used to trigger proper inference of generic method invocations.
+ */
+ public void setExpectedType(TypeBinding expectedType) {
+ // do nothing by default
}
- public abstract StringBuffer printExpression(int indent, StringBuffer output);
+ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+ // do nothing by default
+ }
- public StringBuffer printStatement(int indent, StringBuffer output) {
- return print(indent, output).append(";"); //$NON-NLS-1$
+ public void tagAsNeedCheckCast() {
+ // do nothing by default
}
-
+
public Expression toTypeReference() {
//by default undefined
@@ -493,4 +816,21 @@ public abstract class Expression extends Statement {
return this;
}
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ // do nothing by default
+ }
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+ // do nothing by default
+ }
+ public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+ // do nothing by default
+ }
+ /**
+ * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
+ * or thru a cast expression etc...
+ */
+ public LocalVariableBinding localVariableBinding() {
+ return null;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
index 82bc72d..6219111 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
@@ -21,8 +21,8 @@ public FalseLiteral(int s , int e) {
super(s,e);
}
public void computeConstant() {
-
- constant = Constant.fromValue(false);}
+ constant = Constant.fromValue(false);
+}
/**
* Code generation for false literal
*
@@ -32,8 +32,9 @@ public void computeConstant() {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
- codeStream.iconst_0();
+ if (valueRequired) {
+ codeStream.generateConstant(this.constant, this.implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 7f001c3..9c08cb0 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -17,6 +17,7 @@ import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class FieldDeclaration extends AbstractVariableDeclaration {
+
public FieldBinding binding;
boolean hasBeenResolved = false;
public Javadoc javadoc;
@@ -62,17 +63,28 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
}
// cannot define static non-constant field inside nested class
if (this.binding != null
- && this.binding.isValidBinding()
- && this.binding.isStatic()
- && this.binding.constant == NotAConstant
- && this.binding.declaringClass.isNestedType()
- && this.binding.declaringClass.isClass()
- && !this.binding.declaringClass.isStatic()) {
+ && this.binding.isValidBinding()
+ && this.binding.isStatic()
+ && !this.binding.isConstantValue()
+ && this.binding.declaringClass.isNestedType()
+ && this.binding.declaringClass.isClass()
+ && !this.binding.declaringClass.isStatic()) {
initializationScope.problemReporter().unexpectedStaticModifierForField(
(SourceTypeBinding) this.binding.declaringClass,
this);
}
+ checkAnnotationField: {
+ if (!this.binding.declaringClass.isAnnotationType())
+ break checkAnnotationField;
+ if (this.initialization != null) {
+ if (this.binding.type.isArrayType() && (this.initialization instanceof ArrayInitializer))
+ break checkAnnotationField;
+ if (this.initialization.constant != NotAConstant)
+ break checkAnnotationField;
+ }
+ initializationScope.problemReporter().annotationFieldNeedConstantInitialization(this);
+ }
if (this.initialization != null) {
flowInfo =
this.initialization
@@ -100,7 +112,7 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
int pc = codeStream.position;
boolean isStatic;
if (this.initialization != null
- && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
+ && !((isStatic = this.binding.isStatic()) && this.binding.isConstantValue())) {
// non-static field, need receiver
if (!isStatic)
codeStream.aload_0();
@@ -116,16 +128,13 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
- public TypeBinding getTypeBinding(Scope scope) {
-
- return this.type.getTypeBinding(scope);
- }
-
- public boolean isField() {
-
- return true;
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ public int getKind() {
+ return this.type == null ? ENUM_CONSTANT : FIELD;
}
-
+
public boolean isStatic() {
if (this.binding != null)
@@ -144,6 +153,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
this.hasBeenResolved = true;
+ resolveAnnotations(initializationScope, this.annotations, this.binding);
+
// check if field is hiding some variable - issue is that field binding already got inserted in scope
// thus must lookup separately in super type and outer context
ClassScope classScope = initializationScope.enclosingClassScope();
@@ -153,7 +164,7 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
boolean checkLocal = true;
if (declaringType.superclass != null) {
Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this, false /*do not resolve hidden field*/);
- if (existingVariable != null && existingVariable.isValidBinding()){
+ if (existingVariable != null && this.binding != existingVariable && existingVariable.isValidBinding()){
initializationScope.problemReporter().fieldHiding(this, existingVariable);
checkLocal = false; // already found a matching field
}
@@ -162,8 +173,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
Scope outerScope = classScope.parent;
// only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
// from outer scope. Subsequent static contexts are detected for free.
- Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
- if (existingVariable != null && existingVariable.isValidBinding()
+ Binding existingVariable = outerScope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
+ if (existingVariable != null && this.binding != existingVariable && existingVariable.isValidBinding()
&& (!(existingVariable instanceof FieldBinding)
|| ((FieldBinding) existingVariable).isStatic()
|| !declaringType.isStatic())) {
@@ -172,7 +183,9 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
}
}
- this.type.resolvedType = this.binding.type; // update binding for type reference
+ if (this.type != null ) { // enum constants have no declared type
+ this.type.resolvedType = this.binding.type; // update binding for type reference
+ }
FieldBinding previousField = initializationScope.initializedField;
int previousFieldID = initializationScope.lastVisibleFieldID;
@@ -180,45 +193,48 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
initializationScope.initializedField = this.binding;
initializationScope.lastVisibleFieldID = this.binding.id;
- if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
- initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
- }
// the resolution of the initialization hasn't been done
if (this.initialization == null) {
- this.binding.constant = Constant.NotAConstant;
+ this.binding.setConstant(Constant.NotAConstant);
} else {
// break dead-lock cycles by forcing constant to NotAConstant
- this.binding.constant = Constant.NotAConstant;
-
- TypeBinding typeBinding = this.binding.type;
- TypeBinding initializationTypeBinding;
+ this.binding.setConstant(Constant.NotAConstant);
+ TypeBinding fieldType = this.binding.type;
+ TypeBinding initializationType;
+ this.initialization.setExpectedType(fieldType); // needed in case of generic method invocation
if (this.initialization instanceof ArrayInitializer) {
- if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
- ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+ if ((initializationType = this.initialization.resolveTypeExpecting(initializationScope, fieldType)) != null) {
+ ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationType;
+ this.initialization.computeConversion(initializationScope, fieldType, initializationType);
}
- } else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
-
- if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
- || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
-
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
- } else if (initializationTypeBinding.isCompatibleWith(typeBinding)) {
- this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
-
+ } else if ((initializationType = this.initialization.resolveType(initializationScope)) != null) {
+
+ if (fieldType != initializationType) // must call before computeConversion() and typeMismatchError()
+ initializationScope.compilationUnitScope().recordTypeConversion(fieldType, initializationType);
+ if (this.initialization.isConstantValueOfTypeAssignableToType(initializationType, fieldType)
+ || (fieldType.isBaseType() && BaseTypeBinding.isWidening(fieldType.id, initializationType.id))
+ || initializationType.isCompatibleWith(fieldType)) {
+ this.initialization.computeConversion(initializationScope, fieldType, initializationType);
+ if (initializationType.needsUncheckedConversion(fieldType)) {
+ initializationScope.problemReporter().unsafeRawConversion(this.initialization, initializationType, fieldType);
+ }
+ } else if (initializationScope.environment().options.sourceLevel >= JDK1_5 // autoboxing
+ && (initializationScope.isBoxingCompatibleWith(initializationType, fieldType)
+ || (initializationType.isBaseType() // narrowing then boxing ?
+ && initializationType != null
+ && !fieldType.isBaseType()
+ && initialization.isConstantValueOfTypeAssignableToType(initializationType, initializationScope.environment().computeBoxingType(fieldType))))) {
+ this.initialization.computeConversion(initializationScope, fieldType, initializationType);
} else {
- initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, this);
+ initializationScope.problemReporter().typeMismatchError(initializationType, fieldType, this);
}
if (this.binding.isFinal()){ // cast from constant actual type to variable type
- this.binding.constant =
- this.initialization.constant.castTo(
- (this.binding.type.id << 4) + this.initialization.constant.typeID());
+ this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
}
} else {
- this.binding.constant = NotAConstant;
+ this.binding.setConstant(NotAConstant);
}
}
// Resolve Javadoc comment if one is present
@@ -235,8 +251,8 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
} finally {
initializationScope.initializedField = previousField;
initializationScope.lastVisibleFieldID = previousFieldID;
- if (this.binding.constant == null)
- this.binding.constant = Constant.NotAConstant;
+ if (this.binding.constant() == null)
+ this.binding.setConstant(Constant.NotAConstant);
}
}
}
@@ -244,7 +260,14 @@ public class FieldDeclaration extends AbstractVariableDeclaration {
public void traverse(ASTVisitor visitor, MethodScope scope) {
if (visitor.visit(this, scope)) {
- this.type.traverse(visitor, scope);
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ if (this.type != null) {
+ this.type.traverse(visitor, scope);
+ }
if (this.initialization != null)
this.initialization.traverse(visitor, scope);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 9c4a86d..1e00105 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -21,11 +21,16 @@ public class FieldReference extends Reference implements InvocationSite {
public Expression receiver;
public char[] token;
- public FieldBinding binding, codegenBinding;
+ public FieldBinding binding; // exact binding resulting from lookup
+ protected FieldBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
+ public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
+ public static final int READ = 0;
+ public static final int WRITE = 1;
+
public long nameSourcePosition; //(start<<32)+end
- MethodBinding syntheticReadAccessor, syntheticWriteAccessor;
public TypeBinding receiverType;
-
+ public TypeBinding genericCast;
+
public FieldReference(char[] source, long pos) {
token = source;
@@ -33,7 +38,7 @@ public class FieldReference extends Reference implements InvocationSite {
//by default the position are the one of the field (not true for super access)
sourceStart = (int) (pos >>> 32);
sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
- bits |= BindingIds.FIELD;
+ bits |= Binding.FIELD;
}
@@ -53,7 +58,7 @@ public class FieldReference extends Reference implements InvocationSite {
currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
// we could improve error msg here telling "cannot use compound assignment on final blank field"
}
- manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
}
flowInfo =
receiver
@@ -66,7 +71,7 @@ public class FieldReference extends Reference implements InvocationSite {
.analyseCode(currentScope, flowContext, flowInfo)
.unconditionalInits();
}
- manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
// check if assigning a final field
if (binding.isFinal()) {
@@ -107,13 +112,35 @@ public class FieldReference extends Reference implements InvocationSite {
FlowInfo flowInfo,
boolean valueRequired) {
- receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic());
+ boolean nonStatic = !binding.isStatic();
+ receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
+ if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+
if (valueRequired) {
- manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
}
return flowInfo;
}
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+ if (runtimeTimeType == null || compileTimeType == null)
+ return;
+ // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
+ if (this.binding != null && this.binding.isValidBinding()) {
+ FieldBinding originalBinding = this.binding.original();
+ if (originalBinding != this.binding) {
+ // extra cast needed if method return type has type variable
+ if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+ this.genericCast = originalBinding.type.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+ }
+ }
+ }
+ super.computeConversion(scope, runtimeTimeType, compileTimeType);
+ }
+
public FieldBinding fieldBinding() {
return binding;
@@ -133,11 +160,12 @@ public class FieldReference extends Reference implements InvocationSite {
fieldStore(
codeStream,
this.codegenBinding,
- syntheticWriteAccessor,
+ syntheticAccessors == null ? null : syntheticAccessors[WRITE],
valueRequired);
if (valueRequired) {
codeStream.generateImplicitConversion(assignment.implicitConversion);
}
+ // no need for generic cast as value got dupped
}
/**
@@ -161,27 +189,28 @@ public class FieldReference extends Reference implements InvocationSite {
boolean isStatic = this.codegenBinding.isStatic();
receiver.generateCode(currentScope, codeStream, !isStatic);
if (valueRequired) {
- if (this.codegenBinding.constant == NotAConstant) {
+ if (!this.codegenBinding.isConstantValue()) {
if (this.codegenBinding.declaringClass == null) { // array length
codeStream.arraylength();
} else {
- if (syntheticReadAccessor == null) {
+ if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
if (isStatic) {
codeStream.getstatic(this.codegenBinding);
} else {
codeStream.getfield(this.codegenBinding);
}
} else {
- codeStream.invokestatic(syntheticReadAccessor);
+ codeStream.invokestatic(syntheticAccessors[READ]);
}
}
+ if (this.genericCast != null) codeStream.checkcast(this.genericCast);
codeStream.generateImplicitConversion(implicitConversion);
} else {
if (!isStatic) {
codeStream.invokeObjectGetClass(); // perform null check
codeStream.pop();
}
- codeStream.generateConstant(this.codegenBinding.constant, implicitConversion);
+ codeStream.generateConstant(this.codegenBinding.constant(), implicitConversion);
}
} else {
if (!isStatic){
@@ -207,41 +236,46 @@ public class FieldReference extends Reference implements InvocationSite {
codeStream,
!(isStatic = this.codegenBinding.isStatic()));
if (isStatic) {
- if (syntheticReadAccessor == null) {
+ if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
codeStream.getstatic(this.codegenBinding);
} else {
- codeStream.invokestatic(syntheticReadAccessor);
+ codeStream.invokestatic(syntheticAccessors[READ]);
}
} else {
codeStream.dup();
- if (syntheticReadAccessor == null) {
+ if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
codeStream.getfield(this.codegenBinding);
} else {
- codeStream.invokestatic(syntheticReadAccessor);
+ codeStream.invokestatic(syntheticAccessors[READ]);
}
}
int operationTypeID;
- if ((operationTypeID = implicitConversion >> 4) == T_String) {
- codeStream.generateStringAppend(currentScope, null, expression);
- } else {
- // promote the array reference to the suitable operation type
- codeStream.generateImplicitConversion(implicitConversion);
- // generate the increment value (will by itself be promoted to the operation value)
- if (expression == IntLiteral.One) { // prefix operation
- codeStream.generateConstant(expression.constant, implicitConversion);
- } else {
- expression.generateCode(currentScope, codeStream, true);
- }
- // perform the operation
- codeStream.sendOperator(operator, operationTypeID);
- // cast the value back to the array reference type
- codeStream.generateImplicitConversion(assignmentImplicitConversion);
+ switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+ case T_JavaLangString :
+ case T_JavaLangObject :
+ case T_undefined :
+ codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+ break;
+ default :
+ // promote the array reference to the suitable operation type
+ codeStream.generateImplicitConversion(implicitConversion);
+ // generate the increment value (will by itself be promoted to the operation value)
+ if (expression == IntLiteral.One) { // prefix operation
+ codeStream.generateConstant(expression.constant, implicitConversion);
+ } else {
+ expression.generateCode(currentScope, codeStream, true);
+ }
+ // perform the operation
+ codeStream.sendOperator(operator, operationTypeID);
+ // cast the value back to the array reference type
+ codeStream.generateImplicitConversion(assignmentImplicitConversion);
}
fieldStore(
codeStream,
this.codegenBinding,
- syntheticWriteAccessor,
+ syntheticAccessors == null ? null : syntheticAccessors[WRITE],
valueRequired);
+ // no need for generic cast as value got dupped
}
public void generatePostIncrement(
@@ -256,17 +290,17 @@ public class FieldReference extends Reference implements InvocationSite {
codeStream,
!(isStatic = this.codegenBinding.isStatic()));
if (isStatic) {
- if (syntheticReadAccessor == null) {
+ if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
codeStream.getstatic(this.codegenBinding);
} else {
- codeStream.invokestatic(syntheticReadAccessor);
+ codeStream.invokestatic(syntheticAccessors[READ]);
}
} else {
codeStream.dup();
- if (syntheticReadAccessor == null) {
+ if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
codeStream.getfield(this.codegenBinding);
} else {
- codeStream.invokestatic(syntheticReadAccessor);
+ codeStream.invokestatic(syntheticAccessors[READ]);
}
}
if (valueRequired) {
@@ -286,15 +320,21 @@ public class FieldReference extends Reference implements InvocationSite {
}
}
}
+ codeStream.generateImplicitConversion(implicitConversion);
codeStream.generateConstant(
postIncrement.expression.constant,
implicitConversion);
- codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
+ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
codeStream.generateImplicitConversion(
postIncrement.assignmentImplicitConversion);
- fieldStore(codeStream, this.codegenBinding, syntheticWriteAccessor, false);
+ fieldStore(codeStream, this.codegenBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return null;
}
-
public static final Constant getConstantFor(
FieldBinding binding,
Reference reference,
@@ -318,12 +358,14 @@ public class FieldReference extends Reference implements InvocationSite {
return NotAConstant;
}
if (!binding.isFinal()) {
- return binding.constant = NotAConstant;
+ binding.setConstant(NotAConstant);
+ return NotAConstant;
}
- if (binding.constant != null) {
+ Constant fieldConstant = binding.constant();
+ if (fieldConstant != null) {
if (isImplicit || (reference instanceof QualifiedNameReference
&& binding == ((QualifiedNameReference)reference).binding)) {
- return binding.constant;
+ return fieldConstant;
}
return NotAConstant;
}
@@ -333,17 +375,18 @@ public class FieldReference extends Reference implements InvocationSite {
//has already been compiled. It can only be from a class within
//compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
- SourceTypeBinding typeBinding = (SourceTypeBinding) binding.declaringClass;
- TypeDeclaration typeDecl = typeBinding.scope.referenceContext;
- FieldDeclaration fieldDecl = typeDecl.declarationOf(binding);
+ FieldBinding originalField = binding.original();
+ SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass;
+ TypeDeclaration typeDecl = sourceType.scope.referenceContext;
+ FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
- fieldDecl.resolve(binding.isStatic() //side effect on binding
+ fieldDecl.resolve(originalField.isStatic() //side effect on binding
? typeDecl.staticInitializerScope
: typeDecl.initializerScope);
if (isImplicit || (reference instanceof QualifiedNameReference
&& binding == ((QualifiedNameReference)reference).binding)) {
- return binding.constant;
+ return binding.constant();
}
return NotAConstant;
}
@@ -361,15 +404,19 @@ public class FieldReference extends Reference implements InvocationSite {
/*
* No need to emulate access to protected fields since not implicitly accessed
*/
- public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
if (!flowInfo.isReachable()) return;
+ // if field from parameterized type got found, use the original field at codegen time
+ this.codegenBinding = this.binding.original();
+
if (binding.isPrivate()) {
- if ((currentScope.enclosingSourceType() != binding.declaringClass)
- && (binding.constant == NotAConstant)) {
- syntheticReadAccessor =
- ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+ if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) && !binding.isConstantValue()) {
+ if (syntheticAccessors == null)
+ syntheticAccessors = new MethodBinding[2];
+ syntheticAccessors[isReadAccess ? READ : WRITE] =
+ ((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess);
+ currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
return;
}
@@ -379,8 +426,10 @@ public class FieldReference extends Reference implements InvocationSite {
SourceTypeBinding destinationType =
(SourceTypeBinding) (((QualifiedSuperReference) receiver)
.currentCompatibleType);
- syntheticReadAccessor = destinationType.addSyntheticMethod(binding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+ if (syntheticAccessors == null)
+ syntheticAccessors = new MethodBinding[2];
+ syntheticAccessors[isReadAccess ? READ : WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess);
+ currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
return;
} else if (binding.isProtected()) {
@@ -393,86 +442,31 @@ public class FieldReference extends Reference implements InvocationSite {
SourceTypeBinding currentCompatibleType =
(SourceTypeBinding) enclosingSourceType.enclosingTypeAt(
(bits & DepthMASK) >> DepthSHIFT);
- syntheticReadAccessor = currentCompatibleType.addSyntheticMethod(binding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+ if (syntheticAccessors == null)
+ syntheticAccessors = new MethodBinding[2];
+ syntheticAccessors[isReadAccess ? READ : WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess);
+ currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
return;
}
}
// if the binding declaring class is not visible, need special action
// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
- if (binding.declaringClass != this.receiverType
+ if (this.binding.declaringClass != this.receiverType
&& !this.receiverType.isArrayType()
- && binding.declaringClass != null // array.length
- && binding.constant == NotAConstant
+ && this.binding.declaringClass != null // array.length
+ && !this.binding.isConstantValue()
&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
- && binding.declaringClass.id != T_Object)
+ && this.binding.declaringClass.id != T_JavaLangObject)
//no change for Object fields (in case there was)
- || !binding.declaringClass.canBeSeenBy(currentScope))) {
+ || !this.codegenBinding.declaringClass.canBeSeenBy(currentScope))) {
this.codegenBinding =
currentScope.enclosingSourceType().getUpdatedFieldBinding(
- binding,
- (ReferenceBinding) this.receiverType);
+ this.codegenBinding,
+ (ReferenceBinding) this.receiverType.erasure());
}
}
- /*
- * No need to emulate access to protected fields since not implicitly accessed
- */
- public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-
- if (!flowInfo.isReachable()) return;
- if (binding.isPrivate()) {
- if (currentScope.enclosingSourceType() != binding.declaringClass) {
- syntheticWriteAccessor =
- ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
- return;
- }
-
- } else if (receiver instanceof QualifiedSuperReference) { // qualified super
-
- // qualified super need emulation always
- SourceTypeBinding destinationType =
- (SourceTypeBinding) (((QualifiedSuperReference) receiver)
- .currentCompatibleType);
- syntheticWriteAccessor = destinationType.addSyntheticMethod(binding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
- return;
-
- } else if (binding.isProtected()) {
-
- SourceTypeBinding enclosingSourceType;
- if (((bits & DepthMASK) != 0)
- && binding.declaringClass.getPackage()
- != (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) {
-
- SourceTypeBinding currentCompatibleType =
- (SourceTypeBinding) enclosingSourceType.enclosingTypeAt(
- (bits & DepthMASK) >> DepthSHIFT);
- syntheticWriteAccessor =
- currentCompatibleType.addSyntheticMethod(binding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(binding, this);
- return;
- }
- }
- // if the binding declaring class is not visible, need special action
- // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
- // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
- if (binding.declaringClass != this.receiverType
- && !this.receiverType.isArrayType()
- && binding.declaringClass != null // array.length
- && binding.constant == NotAConstant
- && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
- && binding.declaringClass.id != T_Object)
- //no change for Object fields (in case there was)
- || !binding.declaringClass.canBeSeenBy(currentScope))) {
- this.codegenBinding =
- currentScope.enclosingSourceType().getUpdatedFieldBinding(
- binding,
- (ReferenceBinding) this.receiverType);
- }
- }
public StringBuffer printExpression(int indent, StringBuffer output) {
@@ -509,7 +503,7 @@ public class FieldReference extends Reference implements InvocationSite {
scope.problemReporter().invalidField(this, this.receiverType);
return null;
}
-
+ this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
if (isFieldUseDeprecated(binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
scope.problemReporter().deprecatedField(binding, this);
}
@@ -521,9 +515,8 @@ public class FieldReference extends Reference implements InvocationSite {
if (binding.isStatic()) {
// static field accessed through receiver? legal but unoptimal (optional warning)
if (!(isImplicitThisRcv
- || receiver.isSuper()
|| (receiver instanceof NameReference
- && (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
+ && (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
scope.problemReporter().nonStaticAccessToStaticField(this, binding);
}
if (!isImplicitThisRcv && binding.declaringClass != receiverType) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
index c7d53d6..0fa1908 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
@@ -11,72 +11,105 @@
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.util.FloatUtil;
public class FloatLiteral extends NumberLiteral {
float value;
final static float Float_MIN_VALUE = Float.intBitsToFloat(1); // work-around VAJ problem 1F6IGUU
-public FloatLiteral(char[] token, int s, int e) {
- super(token, s,e);
-}
-public void computeConstant() {
-
- //the source is correctly formated so the exception should never occurs
-
- Float computedValue;
- try {
- computedValue = Float.valueOf(String.valueOf(source));
- } catch (NumberFormatException e) {
- return;
- }
-
- if (computedValue.doubleValue() > Float.MAX_VALUE){
- return; //may be Infinity
+ public FloatLiteral(char[] token, int s, int e) {
+ super(token, s, e);
}
- if (computedValue.floatValue() < Float_MIN_VALUE){
- // see 1F6IGUU
- //only a true 0 can be made of zeros
- //1.00000000e-46f is illegal ....
- label : for (int i = 0; i < source.length; i++) {
- switch (source[i]) {
- case '.' :
- case 'f' :
- case 'F' :
- case '0' :
- break;
- case 'e' :
- case 'E' :
- break label; //exposant are valid !....
- default :
- return; //error
+ public void computeConstant() {
+ Float computedValue;
+ try {
+ computedValue = Float.valueOf(String.valueOf(source));
+ } catch (NumberFormatException e) {
+ // hex floating point literal
+ // being rejected by 1.4 libraries where Float.valueOf(...) doesn't handle hex decimal floats
+ try {
+ float v = FloatUtil.valueOfHexFloatLiteral(source);
+ if (v == Float.POSITIVE_INFINITY) {
+ // error: the number is too large to represent
+ return;
+ }
+ if (Float.isNaN(v)) {
+ // error: the number is too small to represent
+ return;
+ }
+ value = v;
+ constant = Constant.fromValue(v);
+ } catch (NumberFormatException e1) {
+ // if the computation of the constant fails
+ }
+ return;
+ }
+
+ final float floatValue = computedValue.floatValue();
+ if (floatValue > Float.MAX_VALUE) {
+ // error: the number is too large to represent
+ return;
+ }
+ if (floatValue < Float.MIN_VALUE) {
+ // see 1F6IGUU
+ // a true 0 only has '0' and '.' in mantissa
+ // 1.0e-5000d is non-zero, but underflows to 0
+ boolean isHexaDecimal = false;
+ label : for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d
+ switch (source[i]) {
+ case '0' :
+ case '.' :
+ break;
+ case 'x' :
+ case 'X' :
+ isHexaDecimal = true;
+ break;
+ case 'e' :
+ case 'E' :
+ case 'f' :
+ case 'F' :
+ case 'd' :
+ case 'D' :
+ if (isHexaDecimal) {
+ return;
+ }
+ // starting the exponent - mantissa is all zero
+ // no exponent - mantissa is all zero
+ break label;
+ case 'p' :
+ case 'P' :
+ break label;
+ default :
+ // error: the number is too small to represent
+ return;
+ }
}
}
+ value = floatValue;
+ constant = Constant.fromValue(value);
}
- constant = Constant.fromValue(value = computedValue.floatValue());
-}
-/**
- * Code generation for float literal
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- if (valueRequired)
- if ((implicitConversion >> 4) == T_float)
- codeStream.generateInlinedValue(value);
- else
+ /**
+ * Code generation for float literal
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ int pc = codeStream.position;
+ if (valueRequired) {
codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public TypeBinding literalType(BlockScope scope) {
- return FloatBinding;
-}
-public void traverse(ASTVisitor visitor, BlockScope blockScope) {
- visitor.visit(this, blockScope);
- visitor.endVisit(this, blockScope);
-}
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+ public TypeBinding literalType(BlockScope scope) {
+ return FloatBinding;
+ }
+ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 51c5db6..ad6c97a 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -83,14 +83,15 @@ public class ForStatement extends Statement {
// process the condition
LoopingFlowContext condLoopContext = null;
+ FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
if (condition != null) {
if (!isConditionTrue) {
- flowInfo =
+ condInfo =
condition.analyseCode(
scope,
(condLoopContext =
new LoopingFlowContext(flowContext, this, null, null, scope)),
- flowInfo);
+ condInfo);
}
}
@@ -100,28 +101,28 @@ public class ForStatement extends Statement {
if (action == null
|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
if (condLoopContext != null)
- condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+ condLoopContext.complainOnDeferredChecks(scope, condInfo);
if (isConditionTrue) {
return FlowInfo.DEAD_END;
} else {
if (isConditionFalse){
continueLabel = null; // for(;false;p());
}
- actionInfo = flowInfo.initsWhenTrue().copy();
+ actionInfo = condInfo.initsWhenTrue().copy().unconditionalInits().discardNullRelatedInitializations();
loopingContext =
new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
}
} else {
loopingContext =
new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
- FlowInfo initsWhenTrue = flowInfo.initsWhenTrue();
+ FlowInfo initsWhenTrue = condInfo.initsWhenTrue();
condIfTrueInitStateIndex =
currentScope.methodScope().recordInitializationStates(initsWhenTrue);
if (isConditionFalse) {
actionInfo = FlowInfo.DEAD_END;
} else {
- actionInfo = initsWhenTrue.copy();
+ actionInfo = initsWhenTrue.copy().unconditionalInits().discardNullRelatedInitializations();
if (isConditionOptimizedFalse){
actionInfo.setReachMode(FlowInfo.UNREACHABLE);
}
@@ -135,26 +136,31 @@ public class ForStatement extends Statement {
continueLabel = null;
} else {
if (condLoopContext != null)
- condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+ condLoopContext.complainOnDeferredChecks(scope, condInfo);
actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
- loopingContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+ loopingContext.complainOnDeferredChecks(scope, actionInfo);
}
}
// for increments
- if ((continueLabel != null) && (increments != null)) {
- LoopingFlowContext loopContext =
- new LoopingFlowContext(flowContext, this, null, null, scope);
- for (int i = 0, count = increments.length; i < count; i++) {
- actionInfo = increments[i].analyseCode(scope, loopContext, actionInfo);
+ FlowInfo exitBranch = condInfo.initsWhenFalse();
+ exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis
+ if (continueLabel != null) {
+ if (increments != null) {
+ LoopingFlowContext loopContext =
+ new LoopingFlowContext(flowContext, this, null, null, scope);
+ for (int i = 0, count = increments.length; i < count; i++) {
+ actionInfo = increments[i].analyseCode(scope, loopContext, actionInfo);
+ }
+ loopContext.complainOnDeferredChecks(scope, actionInfo);
}
- loopContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+ exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
}
//end of loop
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
loopingContext.initsOnBreak,
isConditionOptimizedTrue,
- flowInfo.initsWhenFalse(),
+ exitBranch,
isConditionOptimizedFalse,
!isConditionTrue /*for(;;){}while(true); unreachable(); */);
mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -221,9 +227,7 @@ public class ForStatement extends Statement {
// May loose some local variable initializations : affecting the local variable attributes
if (preCondInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preCondInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
}
// generate the condition
@@ -290,7 +294,7 @@ public class ForStatement extends Statement {
initializations[i].resolve(scope);
if (condition != null) {
TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
- condition.implicitWidening(type, type);
+ condition.computeConversion(scope, type, type);
}
if (increments != null)
for (int i = 0, length = increments.length; i < length; i++)
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
new file mode 100644
index 0000000..1c1dbb1
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -0,0 +1,461 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+
+public class ForeachStatement extends Statement {
+
+ public LocalDeclaration elementVariable;
+ public int elementVariableImplicitWidening = -1;
+ public Expression collection;
+ public Statement action;
+
+ // set the kind of foreach
+ private int kind;
+ // possible kinds of iterating behavior
+ private static final int ARRAY = 0;
+ private static final int RAW_ITERABLE = 1;
+ private static final int GENERIC_ITERABLE = 2;
+
+ private TypeBinding collectionElementType;
+
+ // loop labels
+ private Label breakLabel;
+ private Label continueLabel;
+
+ public BlockScope scope;
+
+ // secret variables for codegen
+ public LocalVariableBinding indexVariable;
+ public LocalVariableBinding collectionVariable; // to store the collection expression value
+ public LocalVariableBinding maxVariable;
+ // secret variable names
+ private static final char[] SecretIndexVariableName = " index".toCharArray(); //$NON-NLS-1$
+ private static final char[] SecretCollectionVariableName = " collection".toCharArray(); //$NON-NLS-1$
+ private static final char[] SecretMaxVariableName = " max".toCharArray(); //$NON-NLS-1$
+
+ int postCollectionInitStateIndex = -1;
+ int mergedInitStateIndex = -1;
+
+ public ForeachStatement(
+ LocalDeclaration elementVariable,
+ Expression collection,
+ int start) {
+
+ this.elementVariable = elementVariable;
+ this.collection = collection;
+ this.sourceStart = start;
+ this.kind = -1;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+ // initialize break and continue labels
+ breakLabel = new Label();
+ continueLabel = new Label();
+
+ // process the element variable and collection
+ flowInfo = this.elementVariable.analyseCode(scope, flowContext, flowInfo);
+ FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
+ condInfo = this.collection.analyseCode(scope, flowContext, condInfo);
+
+ // element variable will be assigned when iterating
+ condInfo.markAsDefinitelyAssigned(this.elementVariable.binding);
+
+ this.postCollectionInitStateIndex = currentScope.methodScope().recordInitializationStates(condInfo);
+
+ // process the action
+ LoopingFlowContext loopingContext = new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
+ FlowInfo actionInfo = condInfo.initsWhenTrue().copy();
+ FlowInfo exitBranch;
+ if (!(action == null || (action.isEmptyBlock()
+ && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3))) {
+
+ if (!this.action.complainIfUnreachable(actionInfo, scope, false)) {
+ actionInfo = action.analyseCode(scope, loopingContext, actionInfo);
+ }
+
+ // code generation can be optimized when no need to continue in the loop
+ exitBranch = condInfo.initsWhenFalse();
+ exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis
+ if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+ continueLabel = null;
+ } else {
+ actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+ loopingContext.complainOnDeferredChecks(scope, actionInfo);
+ exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
+ }
+ } else {
+ exitBranch = condInfo.initsWhenFalse();
+ }
+
+ // we need the variable to iterate the collection even if the
+ // element variable is not used
+ if (!(this.action == null
+ || this.action.isEmptyBlock()
+ || ((this.action.bits & IsUsefulEmptyStatementMASK) != 0))) {
+ switch(this.kind) {
+ case ARRAY :
+ this.collectionVariable.useFlag = LocalVariableBinding.USED;
+ this.indexVariable.useFlag = LocalVariableBinding.USED;
+ this.maxVariable.useFlag = LocalVariableBinding.USED;
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ this.indexVariable.useFlag = LocalVariableBinding.USED;
+ break;
+ }
+ }
+ //end of loop
+ FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+ loopingContext.initsOnBreak,
+ false,
+ exitBranch,
+ false,
+ true /*for(;;){}while(true); unreachable(); */);
+ mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+
+ /**
+ * For statement code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+ if (this.action == null
+ || this.action.isEmptyBlock()
+ || ((this.action.bits & IsUsefulEmptyStatementMASK) != 0)) {
+ codeStream.exitUserScope(scope);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ // generate the initializations
+ switch(this.kind) {
+ case ARRAY :
+ collection.generateCode(scope, codeStream, true);
+ codeStream.store(this.collectionVariable, false);
+ codeStream.iconst_0();
+ codeStream.store(this.indexVariable, false);
+ codeStream.load(this.collectionVariable);
+ codeStream.arraylength();
+ codeStream.store(this.maxVariable, false);
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ collection.generateCode(scope, codeStream, true);
+ // declaringClass.iterator();
+ final TypeBinding collectionTypeBinding = collection.resolvedType;
+ MethodBinding iteratorMethodBinding =
+ new MethodBinding(
+ AccPublic,
+ "iterator".toCharArray(),//$NON-NLS-1$
+ scope.getJavaUtilIterator(),
+ TypeConstants.NoParameters,
+ TypeConstants.NoExceptions,
+ (ReferenceBinding) collectionTypeBinding);
+ if (collectionTypeBinding.isInterface()) {
+ codeStream.invokeinterface(iteratorMethodBinding);
+ } else {
+ codeStream.invokevirtual(iteratorMethodBinding);
+ }
+ codeStream.store(this.indexVariable, false);
+ break;
+ }
+
+ // label management
+ Label actionLabel = new Label(codeStream);
+ Label conditionLabel = new Label(codeStream);
+ breakLabel.initialize(codeStream);
+ if (this.continueLabel != null) {
+ this.continueLabel.initialize(codeStream);
+ }
+ // jump over the actionBlock
+ codeStream.goto_(conditionLabel);
+
+ // generate the loop action
+ actionLabel.place();
+
+ // generate the loop action
+ if (this.elementVariable.binding.resolvedPosition != -1) {
+ switch(this.kind) {
+ case ARRAY :
+ codeStream.load(this.collectionVariable);
+ codeStream.load(this.indexVariable);
+ codeStream.arrayAt(this.collectionElementType.id);
+ if (this.elementVariableImplicitWidening != -1) {
+ codeStream.generateImplicitConversion(this.elementVariableImplicitWidening);
+ }
+ codeStream.store(this.elementVariable.binding, false);
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ codeStream.load(this.indexVariable);
+ codeStream.invokeJavaUtilIteratorNext();
+ if (this.elementVariable.binding.type.id != T_JavaLangObject) {
+ if (this.elementVariableImplicitWidening != -1) {
+ codeStream.checkcast(this.collectionElementType);
+ codeStream.generateImplicitConversion(this.elementVariableImplicitWidening);
+ } else {
+ codeStream.checkcast(this.elementVariable.binding.type);
+ }
+ }
+ codeStream.store(this.elementVariable.binding, false);
+ break;
+ }
+ codeStream.addVisibleLocalVariable(this.elementVariable.binding);
+ if (this.postCollectionInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(
+ currentScope,
+ this.postCollectionInitStateIndex);
+ }
+ }
+ this.action.generateCode(scope, codeStream);
+
+ // continuation point
+ int continuationPC = codeStream.position;
+ if (this.continueLabel != null) {
+ this.continueLabel.place();
+ // generate the increments for next iteration
+ switch(this.kind) {
+ case ARRAY :
+ codeStream.iinc(this.indexVariable.resolvedPosition, 1);
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ break;
+ }
+ }
+ // generate the condition
+ conditionLabel.place();
+ if (this.postCollectionInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, postCollectionInitStateIndex);
+ }
+ switch(this.kind) {
+ case ARRAY :
+ codeStream.load(this.indexVariable);
+ codeStream.load(this.maxVariable);
+ codeStream.if_icmplt(actionLabel);
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ codeStream.load(this.indexVariable);
+ codeStream.invokeJavaUtilIteratorHasNext();
+ codeStream.ifne(actionLabel);
+ break;
+ }
+ codeStream.recordPositionsFrom(continuationPC, this.elementVariable.sourceStart);
+
+ breakLabel.place();
+ codeStream.exitUserScope(scope);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output) {
+
+ printIndent(tab, output).append("for ("); //$NON-NLS-1$
+ this.elementVariable.print(0, output);
+ output.append(" : ");//$NON-NLS-1$
+ this.collection.print(0, output).append(") "); //$NON-NLS-1$
+ //block
+ if (this.action == null) {
+ output.append(';');
+ } else {
+ output.append('\n');
+ this.action.printStatement(tab + 1, output); //$NON-NLS-1$
+ }
+ return output;
+ }
+
+ public void resolve(BlockScope upperScope) {
+ // use the scope that will hold the init declarations
+ scope = new BlockScope(upperScope);
+ this.elementVariable.resolve(scope); // collection expression can see itemVariable
+ TypeBinding elementType = this.elementVariable.type.resolvedType;
+ TypeBinding collectionType = this.collection.resolveType(scope);
+ this.collection.computeConversion(scope, collectionType, collectionType);
+ boolean hasError = elementType == null || collectionType == null;
+
+ if (!hasError) {
+ if (collectionType.isArrayType()) { // for(E e : E[])
+ this.kind = ARRAY;
+ this.collectionElementType = ((ArrayBinding) collectionType).elementsType();
+ if (!collectionElementType.isCompatibleWith(elementType)
+ && !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+ scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+ }
+ // in case we need to do a conversion
+ int compileTimeTypeID = collectionElementType.id;
+ if (elementType.isBaseType()) {
+ if (!collectionElementType.isBaseType()) {
+ compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = UNBOXING;
+ if (elementType.isBaseType()) {
+ this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ if (collectionElementType.isBaseType()) {
+ int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+ compileTimeTypeID = boxedID;
+ }
+ }
+ } else if (collectionType instanceof ReferenceBinding) {
+ ReferenceBinding iterableType = ((ReferenceBinding)collectionType).findSuperTypeErasingTo(T_JavaLangIterable, false /*Iterable is not a class*/);
+ if (iterableType != null) {
+ if (iterableType.isParameterizedType()) { // for(E e : Iterable)
+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)iterableType;
+ if (parameterizedType.arguments.length == 1) { // per construction can only be one
+ this.kind = GENERIC_ITERABLE;
+ this.collectionElementType = parameterizedType.arguments[0];
+ if (!collectionElementType.isCompatibleWith(elementType)
+ && !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+ scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+ }
+ int compileTimeTypeID = collectionElementType.id;
+ // no conversion needed as only for reference types
+ if (elementType.isBaseType()) {
+ if (!collectionElementType.isBaseType()) {
+ compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = UNBOXING;
+ if (elementType.isBaseType()) {
+ this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ if (collectionElementType.isBaseType()) {
+ int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+ compileTimeTypeID = boxedID;
+ }
+ }
+ }
+ } else if (iterableType.isGenericType()) { // for (T t : Iterable) - in case used inside Iterable itself
+ if (iterableType.typeVariables().length == 1) {
+ this.kind = GENERIC_ITERABLE;
+ this.collectionElementType = iterableType.typeVariables()[0];
+ if (!collectionElementType.isCompatibleWith(elementType)
+ && !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+ scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+ }
+ int compileTimeTypeID = collectionElementType.id;
+ // no conversion needed as only for reference types
+ if (elementType.isBaseType()) {
+ if (!collectionElementType.isBaseType()) {
+ compileTimeTypeID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = UNBOXING;
+ if (elementType.isBaseType()) {
+ this.elementVariableImplicitWidening |= (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ this.elementVariableImplicitWidening = (elementType.id << 4) + compileTimeTypeID;
+ }
+ } else {
+ if (collectionElementType.isBaseType()) {
+ int boxedID = scope.environment().computeBoxingType(collectionElementType).id;
+ this.elementVariableImplicitWidening = BOXING | (compileTimeTypeID << 4) | compileTimeTypeID; // use primitive type in implicit conversion
+ compileTimeTypeID = boxedID;
+ }
+ }
+ }
+ } else if (iterableType.isRawType()) { // for(Object o : Iterable)
+ this.kind = RAW_ITERABLE;
+ this.collectionElementType = scope.getJavaLangObject();
+ if (!collectionElementType.isCompatibleWith(elementType)
+ && !scope.isBoxingCompatibleWith(collectionElementType, elementType)) {
+ scope.problemReporter().notCompatibleTypesErrorInForeach(collection, collectionElementType, elementType);
+ }
+ // no conversion needed as only for reference types
+ }
+ }
+ }
+ switch(this.kind) {
+ case ARRAY :
+ // allocate #index secret variable (of type int)
+ this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, IntBinding, AccDefault, false);
+ scope.addLocalVariable(this.indexVariable);
+ this.indexVariable.setConstant(NotAConstant); // not inlinable
+
+ // allocate #max secret variable
+ this.maxVariable = new LocalVariableBinding(SecretMaxVariableName, IntBinding, AccDefault, false);
+ scope.addLocalVariable(this.maxVariable);
+ this.maxVariable.setConstant(NotAConstant); // not inlinable
+ // add #array secret variable (of collection type)
+ this.collectionVariable = new LocalVariableBinding(SecretCollectionVariableName, collectionType, AccDefault, false);
+ scope.addLocalVariable(this.collectionVariable);
+ this.collectionVariable.setConstant(NotAConstant); // not inlinable
+ break;
+ case RAW_ITERABLE :
+ case GENERIC_ITERABLE :
+ // allocate #index secret variable (of type Iterator)
+ this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, scope.getJavaUtilIterator(), AccDefault, false);
+ scope.addLocalVariable(this.indexVariable);
+ this.indexVariable.setConstant(NotAConstant); // not inlinable
+ break;
+ default :
+ scope.problemReporter().invalidTypeForCollection(collection);
+ }
+ }
+ if (action != null) {
+ action.resolve(scope);
+ }
+ }
+
+ public void traverse(
+ ASTVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ this.elementVariable.traverse(visitor, scope);
+ this.collection.traverse(visitor, scope);
+ if (action != null) {
+ action.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index a262104..223a9ed 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -71,6 +71,11 @@ public class IfStatement extends Statement {
if (isConditionOptimizedFalse) {
thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
}
+ FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
+ if (isConditionOptimizedTrue) {
+ elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
+ }
+ this.condition.checkNullComparison(currentScope, flowContext, flowInfo, thenFlowInfo, elseFlowInfo);
if (this.thenStatement != null) {
// Save info for code gen
thenInitStateIndex =
@@ -84,10 +89,6 @@ public class IfStatement extends Statement {
this.thenExit = !thenFlowInfo.isReachable();
// process the ELSE part
- FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
- if (isConditionOptimizedTrue) {
- elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
- }
if (this.elseStatement != null) {
// signal else clause unnecessarily nested, tolerate else-if code pattern
if (thenFlowInfo == FlowInfo.DEAD_END
@@ -152,9 +153,7 @@ public class IfStatement extends Statement {
true);
// May loose some local variable initializations : affecting the local variable attributes
if (thenInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- thenInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
}
// generate then statement
@@ -221,7 +220,7 @@ public class IfStatement extends Statement {
public void resolve(BlockScope scope) {
TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
- condition.implicitWidening(type, type);
+ condition.computeConversion(scope, type, type);
if (thenStatement != null)
thenStatement.resolve(scope);
if (elseStatement != null)
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
index 9dda67e..546e57c 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -34,7 +35,7 @@ public class ImplicitDocTypeReference extends TypeReference {
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
*/
- public TypeBinding getTypeBinding(Scope scope) {
+ protected TypeBinding getTypeBinding(Scope scope) {
this.constant = NotAConstant;
return this.resolvedType = scope.enclosingSourceType();
}
@@ -52,6 +53,12 @@ public class ImplicitDocTypeReference extends TypeReference {
return true;
}
/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+ */
+ public void traverse(ASTVisitor visitor, BlockScope classScope) {
+ // Do nothing
+ }
+ /* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.TypeReference#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
*/
public void traverse(ASTVisitor visitor, ClassScope classScope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ImportReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
index 4623b2d..fca4408 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
@@ -23,6 +23,7 @@ public class ImportReference extends ASTNode {
public int declarationSourceEnd;
public boolean used;
public int modifiers; // 1.5 addition for static imports
+ public Annotation[] annotations;
public ImportReference(
char[][] tokens,
@@ -37,6 +38,10 @@ public class ImportReference extends ASTNode {
this.sourceStart = (int) (sourcePositions[0] >>> 32);
this.modifiers = modifiers;
}
+
+ public boolean isStatic() {
+ return (this.modifiers & AccStatic) != 0;
+ }
/**
* @return char[][]
@@ -67,6 +72,11 @@ public class ImportReference extends ASTNode {
public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
visitor.visit(this, scope);
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
visitor.endVisit(this, scope);
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Initializer.java b/src/org/eclipse/jdt/internal/compiler/ast/Initializer.java
index ff53718..987149f 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Initializer.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Initializer.java
@@ -57,16 +57,18 @@ public class Initializer extends FieldDeclaration {
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
- public boolean isField() {
-
- return false;
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ public int getKind() {
+ return INITIALIZER;
}
-
+
public boolean isStatic() {
return (modifiers & AccStatic) != 0;
}
-
+
public void parseStatements(
Parser parser,
TypeDeclaration typeDeclaration,
@@ -80,7 +82,9 @@ public class Initializer extends FieldDeclaration {
if (modifiers != 0) {
printIndent(indent, output);
- printModifiers(modifiers, output).append("{\n"); //$NON-NLS-1$
+ printModifiers(modifiers, output);
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+ output.append("{\n"); //$NON-NLS-1$
block.printBody(indent, output);
printIndent(indent, output).append('}');
return output;
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index feacdaf..5a47db8 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
@@ -38,139 +37,13 @@ public class InstanceOfExpression extends OperatorExpression {
FlowContext flowContext,
FlowInfo flowInfo) {
- return expression
+ flowInfo = expression
.analyseCode(currentScope, flowContext, flowInfo)
.unconditionalInits();
+ expression.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+ return flowInfo;
}
- /**
- * Returns false if the instanceof unnecessary
- */
- public final boolean checkCastTypesCompatibility(
- BlockScope scope,
- TypeBinding castType,
- TypeBinding expressionType) {
-
- //A more complete version of this method is provided on
- //CastExpression (it deals with constant and need runtime checkcast)
-
- if (castType == expressionType) return false;
-
- //by grammatical construction, the base type check is not necessary
- if (castType == null || expressionType == null) return true;
-
- //-----------cast to something which is NOT a base type--------------------------
- if (expressionType == NullBinding) {
- // if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
- // needRuntimeCheckcast = true;
- // }
- return false; //null is compatible with every thing
- }
- if (expressionType.isBaseType()) {
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- if (expressionType.isArrayType()) {
- if (castType == expressionType) return false; // identity conversion
-
- if (castType.isArrayType()) {
- //------- (castType.isArray) expressionType.isArray -----------
- TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
- if (exprElementType.isBaseType()) {
- // <---stop the recursion-------
- if (((ArrayBinding) castType).elementsType(scope) != exprElementType)
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
- // recursively on the elements...
- return checkCastTypesCompatibility(
- scope,
- ((ArrayBinding) castType).elementsType(scope),
- exprElementType);
- } else if (
- castType.isClass()) {
- //------(castType.isClass) expressionType.isArray ---------------
- if (castType.id == T_Object) {
- return false;
- }
- } else { //------- (castType.isInterface) expressionType.isArray -----------
- if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
- return true;
- }
- }
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- if (expressionType.isClass()) {
- if (castType.isArrayType()) {
- // ---- (castType.isArray) expressionType.isClass -------
- if (expressionType.id == T_Object) { // potential runtime error
- return true;
- }
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
- if (expressionType.isCompatibleWith(castType)){ // no runtime error
- return false;
- }
- if (castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- return true;
- }
- } else { // ----- (castType.isInterface) expressionType.isClass -------
- if (expressionType.isCompatibleWith(castType))
- return false;
- if (!((ReferenceBinding) expressionType).isFinal()) {
- // a subclass may implement the interface ==> no check at compile time
- return true;
- }
- // no subclass for expressionType, thus compile-time check is valid
- }
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- // if (expressionType.isInterface()) { cannot be anything else
- if (castType.isArrayType()) {
- // ----- (castType.isArray) expressionType.isInterface ------
- if (!(expressionType.id == T_JavaLangCloneable
- || expressionType.id == T_JavaIoSerializable)) {// potential runtime error
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- }
- return true;
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
- if (castType.id == T_Object) { // no runtime error
- return false;
- }
- if (((ReferenceBinding) castType).isFinal()) {
- // no subclass for castType, thus compile-time check is valid
- if (!castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
- }
- } else { // ----- (castType.isInterface) expressionType.isInterface -------
- if (expressionType.isCompatibleWith(castType)) {
- return false;
- }
- if (!castType.isCompatibleWith(expressionType)) {
- MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
- MethodBinding[] expressionTypeMethods =
- ((ReferenceBinding) expressionType).methods();
- int exprMethodsLength = expressionTypeMethods.length;
- for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
- for (int j = 0; j < exprMethodsLength; j++) {
- if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
- && CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector)
- && castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- }
- }
- }
- }
- return true;
- }
/**
* Code generation for instanceOfExpression
*
@@ -186,8 +59,11 @@ public class InstanceOfExpression extends OperatorExpression {
int pc = codeStream.position;
expression.generateCode(currentScope, codeStream, true);
codeStream.instance_of(type.resolvedType);
- if (!valueRequired)
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
codeStream.pop();
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
@@ -196,22 +72,33 @@ public class InstanceOfExpression extends OperatorExpression {
expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
return type.print(0, output);
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#reportIllegalCast(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+ scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+ }
public TypeBinding resolveType(BlockScope scope) {
constant = NotAConstant;
TypeBinding expressionType = expression.resolveType(scope);
- TypeBinding checkType = type.resolveType(scope);
- if (expressionType == null || checkType == null)
+ TypeBinding checkedType = type.resolveType(scope, true /* check bounds*/);
+ if (expressionType == null || checkedType == null)
return null;
- boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType);
- if (!necessary) {
- scope.problemReporter().unnecessaryInstanceof(this, checkType);
+ if (checkedType.isTypeVariable() || checkedType.isBoundParameterizedType() || checkedType.isGenericType()) {
+ scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ } else {
+ checkCastTypesCompatibility(scope, checkedType, expressionType, null);
}
return this.resolvedType = BooleanBinding;
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
+ */
+ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+ scope.problemReporter().unnecessaryInstanceof(this, castType);
+ }
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
index 46a2172..0e7821e 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
@@ -56,7 +56,7 @@ public void computeConstant() {
if (length == 1) { constant = Constant.fromValue(0); return ;}
final int shift,radix;
int j ;
- if ( (source[1] == 'x') | (source[1] == 'X') )
+ if ( (source[1] == 'x') || (source[1] == 'X') )
{ shift = 4 ; j = 2; radix = 16;}
else
{ shift = 3 ; j = 1; radix = 8;}
@@ -94,11 +94,9 @@ public void computeConstant() {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
- if ((implicitConversion >> 4) == T_int)
- codeStream.generateInlinedValue(value);
- else
- codeStream.generateConstant(constant, implicitConversion);
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public TypeBinding literalType(BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/src/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index f683964..03cdba4 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -11,17 +11,20 @@
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser;
/**
* Node representing a structured Javadoc comment
*/
public class Javadoc extends ASTNode {
- public JavadocSingleNameReference[] parameters; // @param
- public TypeReference[] thrownExceptions; // @throws, @exception
+ public JavadocSingleNameReference[] paramReferences; // @param
+ public JavadocSingleTypeReference[] paramTypeParameters; // @param
+ public TypeReference[] exceptionReferences; // @throws, @exception
public JavadocReturnStatement returnStatement; // @return
- public Expression[] references; // @see
+ public Expression[] seeReferences; // @see
public boolean inherited = false;
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
// Store param references for tag with invalid syntax
@@ -37,25 +40,32 @@ public class Javadoc extends ASTNode {
*/
public StringBuffer print(int indent, StringBuffer output) {
printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
- if (this.parameters != null) {
- for (int i = 0, length = this.parameters.length; i < length; i++) {
+ if (this.paramReferences != null) {
+ for (int i = 0, length = this.paramReferences.length; i < length; i++) {
printIndent(indent + 1, output).append(" * @param "); //$NON-NLS-1$
- this.parameters[i].print(indent, output).append('\n');
+ this.paramReferences[i].print(indent, output).append('\n');
+ }
+ }
+ if (this.paramTypeParameters != null) {
+ for (int i = 0, length = this.paramTypeParameters.length; i < length; i++) {
+ printIndent(indent + 1, output).append(" * @param <"); //$NON-NLS-1$
+ this.paramTypeParameters[i].print(indent, output).append(">\n"); //$NON-NLS-1$
}
}
if (this.returnStatement != null) {
- printIndent(indent + 1, output).append(" * @return\n"); //$NON-NLS-1$
+ printIndent(indent + 1, output).append(" * @"); //$NON-NLS-1$
+ this.returnStatement.print(indent, output).append('\n');
}
- if (this.thrownExceptions != null) {
- for (int i = 0, length = this.thrownExceptions.length; i < length; i++) {
+ if (this.exceptionReferences != null) {
+ for (int i = 0, length = this.exceptionReferences.length; i < length; i++) {
printIndent(indent + 1, output).append(" * @throws "); //$NON-NLS-1$
- this.thrownExceptions[i].print(indent, output).append('\n');
+ this.exceptionReferences[i].print(indent, output).append('\n');
}
}
- if (this.references != null) {
- for (int i = 0, length = this.references.length; i < length; i++) {
+ if (this.seeReferences != null) {
+ for (int i = 0, length = this.seeReferences.length; i < length; i++) {
printIndent(indent + 1, output).append(" * @see"); //$NON-NLS-1$
- this.references[i].print(indent, output).append('\n');
+ this.seeReferences[i].print(indent, output).append('\n');
}
}
printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
@@ -66,14 +76,14 @@ public class Javadoc extends ASTNode {
* Resolve type javadoc while a class scope
*/
public void resolve(ClassScope classScope) {
-
// @param tags
- int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+ int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
for (int i = 0; i < paramTagsSize; i++) {
- JavadocSingleNameReference param = this.parameters[i];
+ JavadocSingleNameReference param = this.paramReferences[i];
classScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
}
+ resolveTypeParameterTags(classScope, true);
// @return tags
if (this.returnStatement != null) {
@@ -81,9 +91,9 @@ public class Javadoc extends ASTNode {
}
// @throws/@exception tags
- int throwsTagsLength = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+ int throwsTagsLength = this.exceptionReferences == null ? 0 : this.exceptionReferences.length;
for (int i = 0; i < throwsTagsLength; i++) {
- TypeReference typeRef = this.thrownExceptions[i];
+ TypeReference typeRef = this.exceptionReferences[i];
int start, end;
if (typeRef instanceof JavadocSingleTypeReference) {
JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
@@ -101,27 +111,9 @@ public class Javadoc extends ASTNode {
}
// @see tags
- int seeTagsLength = this.references == null ? 0 : this.references.length;
+ int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length;
for (int i = 0; i < seeTagsLength; i++) {
-
- // Resolve reference
- this.references[i].resolveType(classScope);
-
- // Some unbound field reference might be changed to message send
- // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
- if (this.references[i] instanceof JavadocFieldReference) {
- JavadocFieldReference fieldRef = (JavadocFieldReference) this.references[i];
- if (fieldRef.receiverType != null && fieldRef.binding == null) { // binding was reset in case of valid method reference
- // TODO (frederic) post 3.0 - avoid new instanciation of Compiler AST node
- JavadocMessageSend msgSend = new JavadocMessageSend(fieldRef.token, fieldRef.nameSourcePosition);
- msgSend.receiver = fieldRef.receiver;
- msgSend.receiverType = fieldRef.receiverType;
- msgSend.qualifyingType = fieldRef.receiverType;
- msgSend.superAccess = classScope.enclosingSourceType().isCompatibleWith(msgSend.receiverType);
- msgSend.binding = classScope.findMethod((ReferenceBinding)msgSend.receiverType, msgSend.selector, new TypeBinding[0], msgSend);
- this.references[i] = msgSend;
- }
- }
+ resolveReference(this.seeReferences[i], classScope);
}
}
@@ -132,40 +124,24 @@ public class Javadoc extends ASTNode {
// get method declaration
AbstractMethodDeclaration methDecl = methScope.referenceMethod();
- boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing+AccOverriding)) != 0;
+ boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing | AccOverriding)) != 0;
// @see tags
- int seeTagsLength = this.references == null ? 0 : this.references.length;
+ int seeTagsLength = this.seeReferences == null ? 0 : this.seeReferences.length;
boolean superRef = false;
for (int i = 0; i < seeTagsLength; i++) {
// Resolve reference
- this.references[i].resolveType(methScope);
+ resolveReference(this.seeReferences[i], methScope);
- // Some unbound field reference might be changed to message send
- // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
- if (this.references[i] instanceof JavadocFieldReference) {
- JavadocFieldReference fieldRef = (JavadocFieldReference) this.references[i];
- if (fieldRef.receiverType != null && fieldRef.binding == null) { // binding was reset in case of valid method reference
- // TODO (frederic) post 3.0 - avoid new instanciation of Compiler AST node
- JavadocMessageSend msgSend = new JavadocMessageSend(fieldRef.token, fieldRef.nameSourcePosition);
- msgSend.receiver = fieldRef.receiver;
- msgSend.receiverType = fieldRef.receiverType;
- msgSend.qualifyingType = fieldRef.receiverType;
- msgSend.superAccess = methScope.enclosingSourceType().isCompatibleWith(msgSend.receiverType);
- msgSend.binding = methScope.findMethod((ReferenceBinding)msgSend.receiverType, msgSend.selector, new TypeBinding[0], msgSend);
- this.references[i] = msgSend;
- }
- }
-
// see whether we can have a super reference
try {
if (methDecl != null && (methDecl.isConstructor() || overriding) && !superRef) {
- if (this.references[i] instanceof JavadocMessageSend) {
- JavadocMessageSend messageSend = (JavadocMessageSend) this.references[i];
+ if (this.seeReferences[i] instanceof JavadocMessageSend) {
+ JavadocMessageSend messageSend = (JavadocMessageSend) this.seeReferences[i];
// if binding is valid then look if we have a reference to an overriden method/constructor
if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
- if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.receiverType) &&
+ if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.actualReceiverType) &&
CharOperation.equals(messageSend.selector, methDecl.selector) &&
(messageSend.binding.returnType == methDecl.binding.returnType)) {
if (messageSend.arguments == null && methDecl.arguments == null) {
@@ -177,8 +153,8 @@ public class Javadoc extends ASTNode {
}
}
}
- else if (this.references[i] instanceof JavadocAllocationExpression) {
- JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[i];
+ else if (this.seeReferences[i] instanceof JavadocAllocationExpression) {
+ JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.seeReferences[i];
// if binding is valid then look if we have a reference to an overriden method/constructor
if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
if (methDecl.binding.declaringClass.isCompatibleWith(allocationExpr.resolvedType)) {
@@ -203,11 +179,12 @@ public class Javadoc extends ASTNode {
// @param tags
resolveParamTags(methScope, reportMissing);
+ resolveTypeParameterTags(methScope, reportMissing);
// @return tags
if (this.returnStatement == null) {
if (reportMissing && methDecl != null) {
- if (!methDecl.isConstructor() && !methDecl.isClinit()) {
+ if (methDecl.isMethod()) {
MethodDeclaration meth = (MethodDeclaration) methDecl;
if (meth.binding.returnType != VoidBinding) {
// method with return should have @return tag
@@ -229,17 +206,78 @@ public class Javadoc extends ASTNode {
}
}
+ private void resolveReference(Expression reference, Scope scope) {
+
+ // Perform resolve
+ switch (scope.kind) {
+ case Scope.METHOD_SCOPE:
+ reference.resolveType((MethodScope)scope);
+ break;
+ case Scope.CLASS_SCOPE:
+ reference.resolveType((ClassScope)scope);
+ break;
+ }
+
+ // Verify field references
+ boolean verifyValues = scope.environment().options.sourceLevel >= ClassFileConstants.JDK1_5;
+ if (reference instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+ int modifiers = fieldRef.binding==null ? -1 : fieldRef.binding.modifiers;
+
+ // Verify if this is a method reference
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51911
+ if (fieldRef.methodBinding != null) {
+ // cannot refer to method for @value tag
+ if (fieldRef.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) {
+ scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, modifiers);
+ }
+ else if (fieldRef.receiverType != null) {
+ fieldRef.superAccess = scope.enclosingSourceType().isCompatibleWith(fieldRef.receiverType);
+ fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.receiverType, fieldRef.token, new TypeBinding[0], fieldRef);
+ }
+ }
+
+ // Verify whether field ref should be static or not (for @value tags)
+ else if (verifyValues && fieldRef.binding != null && fieldRef.binding.isValidBinding()) {
+ if (fieldRef.tagValue == AbstractCommentParser.TAG_VALUE_VALUE && !fieldRef.binding.isStatic()) {
+ scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, modifiers);
+ }
+ }
+ }
+
+ // If not 1.5 level, verification is finished
+ if (!verifyValues) return;
+
+ // Verify that message reference are not used for @value tags
+ else if (reference instanceof JavadocMessageSend) {
+ JavadocMessageSend msgSend = (JavadocMessageSend) reference;
+ int modifiers = msgSend.binding==null ? -1 : msgSend.binding.modifiers;
+ if (msgSend.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) { // cannot refer to method for @value tag
+ scope.problemReporter().javadocInvalidValueReference(msgSend.sourceStart, msgSend.sourceEnd, modifiers);
+ }
+ }
+
+ // Verify that constructorreference are not used for @value tags
+ else if (reference instanceof JavadocAllocationExpression) {
+ JavadocAllocationExpression alloc = (JavadocAllocationExpression) reference;
+ int modifiers = alloc.binding==null ? -1 : alloc.binding.modifiers;
+ if (alloc.tagValue == AbstractCommentParser.TAG_VALUE_VALUE) { // cannot refer to method for @value tag
+ scope.problemReporter().javadocInvalidValueReference(alloc.sourceStart, alloc.sourceEnd, modifiers);
+ }
+ }
+ }
+
/*
* Resolve @param tags while method scope
*/
private void resolveParamTags(MethodScope methScope, boolean reportMissing) {
AbstractMethodDeclaration md = methScope.referenceMethod();
- int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+ int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
// If no referenced method (field initializer for example) then report a problem for each param tag
if (md == null) {
for (int i = 0; i < paramTagsSize; i++) {
- JavadocSingleNameReference param = this.parameters[i];
+ JavadocSingleNameReference param = this.paramReferences[i];
methScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
}
return;
@@ -251,7 +289,7 @@ public class Javadoc extends ASTNode {
if (reportMissing) {
for (int i = 0; i < argumentsSize; i++) {
Argument arg = md.arguments[i];
- methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+ methScope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, md.binding.modifiers);
}
}
} else {
@@ -260,14 +298,14 @@ public class Javadoc extends ASTNode {
// Scan all @param tags
for (int i = 0; i < paramTagsSize; i++) {
- JavadocSingleNameReference param = this.parameters[i];
+ JavadocSingleNameReference param = this.paramReferences[i];
param.resolve(methScope);
if (param.binding != null && param.binding.isValidBinding()) {
// Verify duplicated tags
boolean found = false;
for (int j = 0; j < maxBindings && !found; j++) {
if (bindings[j] == param.binding) {
- methScope.problemReporter().javadocDuplicatedParamTag(param, md.binding.modifiers);
+ methScope.problemReporter().javadocDuplicatedParamTag(param.token, param.sourceStart, param.sourceEnd, md.binding.modifiers);
found = true;
}
}
@@ -289,7 +327,103 @@ public class Javadoc extends ASTNode {
}
}
if (!found) {
- methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+ methScope.problemReporter().javadocMissingParamTag(arg.name, arg.sourceStart, arg.sourceEnd, md.binding.modifiers);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Resolve @param tags for type parameters
+ */
+ private void resolveTypeParameterTags(Scope scope, boolean reportMissing) {
+ int paramTypeParamLength = this.paramTypeParameters == null ? 0 : this.paramTypeParameters.length;
+
+ // Get declaration infos
+ TypeDeclaration typeDeclaration = null;
+ AbstractMethodDeclaration methodDeclaration = null;
+ TypeVariableBinding[] typeVariables = null;
+ int modifiers = -1;
+ switch (scope.kind) {
+ case Scope.METHOD_SCOPE:
+ methodDeclaration = ((MethodScope)scope).referenceMethod();
+ // If no referenced method (field initializer for example) then report a problem for each param tag
+ if (methodDeclaration == null) {
+ for (int i = 0; i < paramTypeParamLength; i++) {
+ JavadocSingleNameReference param = this.paramReferences[i];
+ scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+ }
+ return;
+ }
+ typeVariables = methodDeclaration.binding.typeVariables;
+ modifiers = methodDeclaration.binding.modifiers;
+ break;
+ case Scope.CLASS_SCOPE:
+ typeDeclaration = ((ClassScope) scope).referenceContext;
+ typeVariables = typeDeclaration.binding.typeVariables;
+ modifiers = typeDeclaration.binding.modifiers;
+ break;
+ }
+
+ // If no type variables then report a problem for each param type parameter tag
+ if (typeVariables == null || typeVariables.length == 0) {
+ for (int i = 0; i < paramTypeParamLength; i++) {
+ JavadocSingleTypeReference param = this.paramTypeParameters[i];
+ scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+ }
+ return;
+ }
+
+ // If no param tags then report a problem for each declaration type parameter
+ TypeParameter[] parameters = typeDeclaration==null ? methodDeclaration.typeParameters() : typeDeclaration.typeParameters;
+ int typeParametersLength = parameters == null ? 0 : parameters.length;
+ if (paramTypeParamLength == 0) {
+ if (reportMissing) {
+ for (int i = 0, l=parameters.length; i= JDK1_5 // autoboxing
+ && (scope.isBoxingCompatibleWith(initializationType, variableType)
+ || (initializationType.isBaseType() // narrowing then boxing ?
+ && initializationType != null
+ && !variableType.isBaseType()
+ && initialization.isConstantValueOfTypeAssignableToType(initializationType, scope.environment().computeBoxingType(variableType))))) {
+ this.initialization.computeConversion(scope, variableType, initializationType);
+ } else {
+ scope.problemReporter().typeMismatchError(initializationType, variableType, this);
+ }
}
}
@@ -201,10 +226,10 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
// (the optimization of the constant propagation will be done later on)
// cast from constant actual type to variable type
if (binding != null) {
- binding.constant =
+ binding.setConstant(
binding.isFinal()
- ? initialization.constant.castTo((typeBinding.id << 4) + initialization.constant.typeID())
- : NotAConstant;
+ ? initialization.constant.castTo((variableType.id << 4) + initialization.constant.typeID())
+ : NotAConstant);
}
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
index 70294b5..6da299b 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
@@ -38,7 +38,7 @@ public void computeConstant() {
{ if (length == 1) { constant = Constant.fromValue(0L); return; }
final int shift,radix;
int j ;
- if ( (source[1] == 'x') | (source[1] == 'X') )
+ if ( (source[1] == 'x') || (source[1] == 'X') )
{ shift = 4 ; j = 2; radix = 16;}
else
{ shift = 3 ; j = 1; radix = 8;}
@@ -85,11 +85,9 @@ public void computeConstant() {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
- if ((implicitConversion >> 4) == T_long)
- codeStream.generateInlinedValue(value);
- else
- codeStream.generateConstant(constant, implicitConversion);
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public TypeBinding literalType(BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java
new file mode 100644
index 0000000..65f1bd5
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/MarkerAnnotation.java
@@ -0,0 +1,35 @@
+/*
+ * Created on 2004-03-11
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class MarkerAnnotation extends Annotation {
+
+ public MarkerAnnotation(TypeReference type, int sourceStart) {
+ this.type = type;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = type.sourceEnd;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+ */
+ public MemberValuePair[] memberValuePairs() {
+ return NoValuePairs;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+ public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
new file mode 100644
index 0000000..04d0ee8
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * MemberValuePair node
+ */
+public class MemberValuePair extends ASTNode {
+
+ public char[] name;
+ public Expression value;
+ public MethodBinding binding;
+
+ public MemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) {
+ this.name = token;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ this.value = value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+ */
+ public StringBuffer print(int indent, StringBuffer output) {
+ output
+ .append(name)
+ .append(" = "); //$NON-NLS-1$
+ value.print(indent, output);
+ return output;
+ }
+
+ public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
+
+ if (requiredType == null)
+ return;
+ if (this.value == null)
+ return;
+
+ this.value.setExpectedType(requiredType); // needed in case of generic method invocation
+ if (this.value instanceof ArrayInitializer) {
+ ArrayInitializer initializer = (ArrayInitializer) this.value;
+ if ((initializer.resolveTypeExpecting(scope, this.binding.returnType)) != null) {
+ this.value.resolvedType = initializer.binding = (ArrayBinding) this.binding.returnType;
+ }
+ } else {
+ this.value.resolveType(scope);
+ }
+ TypeBinding valueType = this.value.resolvedType;
+ if (valueType == null)
+ return;
+
+ TypeBinding leafType = requiredType.leafComponentType();
+ if (!((this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
+ || (requiredType.isBaseType() && BaseTypeBinding.isWidening(requiredType.id, valueType.id)))
+ || valueType.isCompatibleWith(requiredType))) {
+
+ if (!(requiredType.isArrayType()
+ && requiredType.dimensions() == 1
+ && (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
+ || (leafType.isBaseType() && BaseTypeBinding.isWidening(leafType.id, valueType.id)))
+ || valueType.isCompatibleWith(leafType))) {
+
+ scope.problemReporter().typeMismatchError(valueType, requiredType, this.value);
+ return; // may allow to proceed to find more errors at once
+ }
+ } else {
+ scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
+ this.value.computeConversion(scope, requiredType, valueType);
+ }
+
+ // annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
+ checkAnnotationMethodType: {
+ switch (leafType.erasure().id) {
+ case T_byte :
+ case T_short :
+ case T_char :
+ case T_int :
+ case T_long :
+ case T_float :
+ case T_double :
+ case T_boolean :
+ case T_JavaLangString :
+ if (this.value instanceof ArrayInitializer) {
+ ArrayInitializer initializer = (ArrayInitializer) this.value;
+ final Expression[] expressions = initializer.expressions;
+ if (expressions != null) {
+ for (int i =0, max = expressions.length; i < max; i++) {
+ if (expressions[i].constant == NotAConstant) {
+ scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i]);
+ }
+ }
+ }
+ } else if (this.value.constant == NotAConstant) {
+ scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value);
+ }
+ break checkAnnotationMethodType;
+ case T_JavaLangClass :
+ if (this.value instanceof ArrayInitializer) {
+ ArrayInitializer initializer = (ArrayInitializer) this.value;
+ final Expression[] expressions = initializer.expressions;
+ if (expressions != null) {
+ for (int i =0, max = expressions.length; i < max; i++) {
+ if (!(expressions[i] instanceof ClassLiteralAccess)) {
+ scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, expressions[i]);
+ }
+ }
+ }
+ } else if (!(this.value instanceof ClassLiteralAccess)) {
+ scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, this.value);
+ }
+ break checkAnnotationMethodType;
+ }
+ if (leafType.isEnum()) {
+ break checkAnnotationMethodType;
+ }
+ if (leafType.isAnnotationType()) {
+ break checkAnnotationMethodType;
+ }
+ }
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.value != null) {
+ this.value.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+ public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.value != null) {
+ this.value.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index a9a2e9d..05b78da 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -18,20 +19,28 @@ import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class MessageSend extends Expression implements InvocationSite {
+
public Expression receiver ;
public char[] selector ;
public Expression[] arguments ;
- public MethodBinding binding, codegenBinding;
+ public MethodBinding binding; // exact binding resulting from lookup
+ protected MethodBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
+ MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation
+ public TypeBinding expectedType; // for generic method invocation (return type inference)
public long nameSourcePosition ; //(start<<32)+end
- MethodBinding syntheticAccessor;
-
- public TypeBinding receiverType, qualifyingType;
+ public TypeBinding actualReceiverType;
+ public TypeBinding valueCast; // extra reference type cast to perform on method returned value
+ public TypeReference[] typeArguments;
+ public TypeBinding[] genericTypeArguments;
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic()).unconditionalInits();
+ boolean nonStatic = !binding.isStatic();
+ flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
+ if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+
if (arguments != null) {
int length = arguments.length;
for (int i = 0; i < length; i++) {
@@ -46,7 +55,31 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
manageSyntheticAccessIfNecessary(currentScope, flowInfo);
return flowInfo;
}
-
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+ if (runtimeTimeType == null || compileTimeType == null)
+ return;
+ // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
+ if (this.binding != null && this.binding.isValidBinding()) {
+ MethodBinding originalBinding = this.binding.original();
+ if (originalBinding != this.binding) {
+ // extra cast needed if method return type has type variable
+ if ((originalBinding.returnType.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+ this.valueCast = originalBinding.returnType.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+ }
+ } else if (this.actualReceiverType.isArrayType()
+ && runtimeTimeType.id != T_JavaLangObject
+ && this.binding.parameters == NoParameters
+ && scope.environment().options.complianceLevel >= JDK1_5
+ && CharOperation.equals(this.binding.selector, CLONE)) {
+ // from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast
+ this.valueCast = runtimeTimeType;
+ }
+ }
+ super.computeConversion(scope, runtimeTimeType, compileTimeType);
+}
/**
* MessageSend code generation
*
@@ -59,7 +92,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
int pc = codeStream.position;
// generate receiver/enclosing instance access
- boolean isStatic = codegenBinding.isStatic();
+ boolean isStatic = this.codegenBinding.isStatic();
// outer access ?
if (!isStatic && ((bits & DepthMASK) != 0) && receiver.isImplicitThis()){
// outer method can be reached through emulation if implicit access
@@ -70,23 +103,19 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
receiver.generateCode(currentScope, codeStream, !isStatic);
}
// generate arguments
- if (arguments != null){
- for (int i = 0, max = arguments.length; i < max; i++){
- arguments[i].generateCode(currentScope, codeStream, true);
- }
- }
+ generateArguments(binding, arguments, currentScope, codeStream);
// actual message invocation
if (syntheticAccessor == null){
if (isStatic){
- codeStream.invokestatic(codegenBinding);
+ codeStream.invokestatic(this.codegenBinding);
} else {
- if( (receiver.isSuper()) || codegenBinding.isPrivate()){
- codeStream.invokespecial(codegenBinding);
+ if( (receiver.isSuper()) || this.codegenBinding.isPrivate()){
+ codeStream.invokespecial(this.codegenBinding);
} else {
- if (codegenBinding.declaringClass.isInterface()){
- codeStream.invokeinterface(codegenBinding);
+ if ((this.codegenBinding.declaringClass.modifiers & AccInterface) != 0) { // interface or annotation type
+ codeStream.invokeinterface(this.codegenBinding);
} else {
- codeStream.invokevirtual(codegenBinding);
+ codeStream.invokevirtual(this.codegenBinding);
}
}
}
@@ -96,6 +125,8 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
// operation on the returned value
if (valueRequired){
// implicit conversion if necessary
+ if (this.valueCast != null)
+ codeStream.checkcast(this.valueCast);
codeStream.generateImplicitConversion(implicitConversion);
} else {
// pop return value if any
@@ -112,6 +143,12 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
}
codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); // highlight selector
}
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+public TypeBinding[] genericTypeArguments() {
+ return this.genericTypeArguments;
+}
public boolean isSuperAccess() {
return receiver.isSuper();
}
@@ -121,13 +158,16 @@ public boolean isTypeAccess() {
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
if (!flowInfo.isReachable()) return;
- if (binding.isPrivate()){
+
+ // if method from parameterized type got found, use the original method at codegen time
+ this.codegenBinding = this.binding.original();
+ if (this.binding.isPrivate()){
// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)
- if (currentScope.enclosingSourceType() != binding.declaringClass){
+ if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){
- syntheticAccessor = ((SourceTypeBinding)binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
+ currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
return;
}
@@ -135,44 +175,60 @@ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo f
// qualified super need emulation always
SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)receiver).currentCompatibleType);
- syntheticAccessor = destinationType.addSyntheticMethod(binding, isSuperAccess());
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
+ currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
return;
} else if (binding.isProtected()){
SourceTypeBinding enclosingSourceType;
if (((bits & DepthMASK) != 0)
- && binding.declaringClass.getPackage()
+ && this.codegenBinding.declaringClass.getPackage()
!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){
SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
- syntheticAccessor = currentCompatibleType.addSyntheticMethod(binding, isSuperAccess());
- currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
+ currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
return;
}
}
+
// if the binding declaring class is not visible, need special action
// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
// and not from Object or implicit static method call.
- if (binding.declaringClass != this.qualifyingType
- && !this.qualifyingType.isArrayType()
+ if (this.binding.declaringClass != this.actualReceiverType
+ && !this.actualReceiverType.isArrayType()
&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
- && (!receiver.isImplicitThis() || !binding.isStatic())
- && binding.declaringClass.id != T_Object) // no change for Object methods
- || !binding.declaringClass.canBeSeenBy(currentScope))) {
+ && (!receiver.isImplicitThis() || !this.codegenBinding.isStatic())
+ && this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods
+ || !this.binding.declaringClass.canBeSeenBy(currentScope))) {
- this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(binding, (ReferenceBinding) this.qualifyingType);
+ this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(
+ this.codegenBinding, (ReferenceBinding) this.actualReceiverType.erasure());
// Post 1.4.0 target, array clone() invocations are qualified with array type
// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
}
}
+public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.UNKNOWN;
+}
+
public StringBuffer printExpression(int indent, StringBuffer output){
if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
+ if (this.typeArguments != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeArguments.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeArguments[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArguments[max].print(0, output);
+ output.append('>');
+ }
output.append(selector).append('(') ; //$NON-NLS-1$
if (arguments != null) {
for (int i = 0; i < arguments.length ; i ++) {
@@ -188,18 +244,32 @@ public TypeBinding resolveType(BlockScope scope) {
// Base type promotion
constant = NotAConstant;
- boolean receiverCast = false, argumentsCast = false;
+ boolean receiverCast = false, argsContainCast = false;
if (this.receiver instanceof CastExpression) {
this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
receiverCast = true;
}
- this.qualifyingType = this.receiverType = receiver.resolveType(scope);
- if (receiverCast && this.receiverType != null) {
+ this.actualReceiverType = receiver.resolveType(scope);
+ if (receiverCast && this.actualReceiverType != null) {
// due to change of declaring class with receiver type, only identity cast should be notified
- if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) {
- scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
+ if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) {
+ scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
}
}
+ // resolve type arguments (for generic constructor call)
+ if (this.typeArguments != null) {
+ int length = this.typeArguments.length;
+ boolean argHasError = false; // typeChecks all arguments
+ this.genericTypeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ if ((this.genericTypeArguments[i] = this.typeArguments[i].resolveType(scope, true /* check bounds*/)) == null) {
+ argHasError = true;
+ }
+ }
+ if (argHasError) {
+ return null;
+ }
+ }
// will check for null after args are resolved
TypeBinding[] argumentTypes = NoParameters;
if (arguments != null) {
@@ -210,75 +280,92 @@ public TypeBinding resolveType(BlockScope scope) {
Expression argument = arguments[i];
if (argument instanceof CastExpression) {
argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
- argumentsCast = true;
+ argsContainCast = true;
}
if ((argumentTypes[i] = argument.resolveType(scope)) == null){
argHasError = true;
}
}
if (argHasError) {
- if(receiverType instanceof ReferenceBinding) {
+ if(actualReceiverType instanceof ReferenceBinding) {
// record any selector match, for clients who may still need hint about possible method match
- this.codegenBinding = this.binding = scope.findMethod((ReferenceBinding)receiverType, selector, new TypeBinding[]{}, this);
+ this.binding = scope.findMethod((ReferenceBinding)actualReceiverType, selector, new TypeBinding[]{}, this);
}
return null;
}
}
- if (this.receiverType == null)
+ if (this.actualReceiverType == null) {
return null;
-
+ }
// base type cannot receive any message
- if (this.receiverType.isBaseType()) {
- scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+ if (this.actualReceiverType.isBaseType()) {
+ scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
return null;
}
- this.codegenBinding = this.binding =
+ this.binding =
receiver.isImplicitThis()
? scope.getImplicitMethod(selector, argumentTypes, this)
- : scope.getMethod(this.receiverType, selector, argumentTypes, this);
+ : scope.getMethod(this.actualReceiverType, selector, argumentTypes, this);
if (!binding.isValidBinding()) {
if (binding.declaringClass == null) {
- if (this.receiverType instanceof ReferenceBinding) {
- binding.declaringClass = (ReferenceBinding) this.receiverType;
+ if (this.actualReceiverType instanceof ReferenceBinding) {
+ binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
} else {
- scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+ scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
return null;
}
}
scope.problemReporter().invalidMethod(this, binding);
+ MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
+ switch (this.binding.problemId()) {
+ case ProblemReasons.Ambiguous :
+ case ProblemReasons.NotVisible :
+ case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+ case ProblemReasons.NonStaticReferenceInStaticContext :
+ case ProblemReasons.ReceiverTypeNotVisible :
+ case ProblemReasons.ParameterBoundMismatch :
+ // only steal returnType in cases listed above
+ if (closestMatch != null) this.resolvedType = closestMatch.returnType;
+ default :
+ }
// record the closest match, for clients who may still need hint about possible method match
- if (binding instanceof ProblemMethodBinding){
- MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
- if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+ if (closestMatch != null) {
+ this.binding = closestMatch;
+ if (closestMatch.isPrivate() && !scope.isDefinedInMethod(closestMatch)) {
+ // ignore cases where method is used from within inside itself (e.g. direct recursions)
+ closestMatch.original().modifiers |= AccPrivateUsed;
+ }
}
- return this.resolvedType = this.binding == null ? null : this.binding.returnType;
+ return this.resolvedType;
}
if (!binding.isStatic()) {
// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
if (receiver instanceof NameReference
- && (((NameReference) receiver).bits & BindingIds.TYPE) != 0) {
+ && (((NameReference) receiver).bits & Binding.TYPE) != 0) {
scope.problemReporter().mustUseAStaticMethod(this, binding);
+ } else {
+ // compute generic cast if necessary
+ TypeBinding expectedReceiverType = this.actualReceiverType.erasure().isCompatibleWith(this.binding.declaringClass.erasure())
+ ? this.actualReceiverType
+ : this.binding.declaringClass;
+ receiver.computeConversion(scope, expectedReceiverType, actualReceiverType);
+ if (expectedReceiverType != this.actualReceiverType) this.actualReceiverType = expectedReceiverType;
}
} else {
// static message invoked through receiver? legal but unoptimal (optional warning).
if (!(receiver.isImplicitThis()
|| receiver.isSuper()
|| (receiver instanceof NameReference
- && (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
+ && (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
scope.problemReporter().nonStaticAccessToStaticMethod(this, binding);
}
- if (!receiver.isImplicitThis() && binding.declaringClass != receiverType) {
+ if (!receiver.isImplicitThis() && binding.declaringClass != actualReceiverType) {
scope.problemReporter().indirectAccessToStaticMethod(this, binding);
}
}
- if (arguments != null) {
- for (int i = 0; i < arguments.length; i++) {
- arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
- }
- if (argumentsCast) {
- CastExpression.checkNeedForArgumentCasts(scope, this.receiver, receiverType, binding, this.arguments, argumentTypes, this);
- }
- }
+ if (this.arguments != null)
+ checkInvocationArguments(scope, this.receiver, actualReceiverType, binding, this.arguments, argumentTypes, argsContainCast, this);
+
//-------message send that are known to fail at compile time-----------
if (binding.isAbstract()) {
if (receiver.isSuper()) {
@@ -289,11 +376,28 @@ public TypeBinding resolveType(BlockScope scope) {
if (isMethodUseDeprecated(binding, scope))
scope.problemReporter().deprecatedMethod(binding, this);
- return this.resolvedType = binding.returnType;
+ // from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
+ if (actualReceiverType.isArrayType()
+ && this.binding.parameters == NoParameters
+ && scope.environment().options.complianceLevel >= JDK1_5
+ && CharOperation.equals(this.binding.selector, CLONE)) {
+ this.resolvedType = actualReceiverType;
+ } else {
+ this.resolvedType = this.binding.returnType;
+ }
+ return this.resolvedType;
}
+
public void setActualReceiverType(ReferenceBinding receiverType) {
- this.qualifyingType = receiverType;
+ this.actualReceiverType = receiverType;
+}
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+public void setExpectedType(TypeBinding expectedType) {
+ this.expectedType = expectedType;
}
+
public void setDepth(int depth) {
bits &= ~DepthMASK; // flush previous depth if any
if (depth > 0) {
@@ -307,6 +411,11 @@ public void setFieldIndex(int depth) {
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
if (visitor.visit(this, blockScope)) {
receiver.traverse(visitor, blockScope);
+ if (this.typeArguments != null) {
+ for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+ this.typeArguments[i].traverse(visitor, blockScope);
+ }
+ }
if (arguments != null) {
int argumentsLength = arguments.length;
for (int i = 0; i < argumentsLength; i++)
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index b738665..c9de4c6 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
@@ -23,7 +24,8 @@ import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
public class MethodDeclaration extends AbstractMethodDeclaration {
public TypeReference returnType;
-
+ public TypeParameter[] typeParameters;
+
/**
* MethodDeclaration constructor comment.
*/
@@ -49,10 +51,14 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
}
}
+ // skip enum implicit methods
+ if (binding.declaringClass.isEnum() && (this.selector == TypeConstants.VALUES || this.selector == TypeConstants.VALUEOF))
+ return;
+
// may be in a non necessary for innerclass with static final constant fields
if (binding.isAbstract() || binding.isNative())
return;
-
+
ExceptionHandlingFlowContext methodContext =
new ExceptionHandlingFlowContext(
initializationContext,
@@ -61,6 +67,12 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
scope,
FlowInfo.DEAD_END);
+ // tag parameters as being set
+ if (this.arguments != null) {
+ for (int i = 0, count = this.arguments.length; i < count; i++) {
+ flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
+ }
+ }
// propagate to statements
if (statements != null) {
boolean didAlreadyComplain = false;
@@ -89,6 +101,11 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
}
}
+ public boolean isMethod() {
+
+ return true;
+ }
+
public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
//fill up the method body with statement
@@ -110,29 +127,35 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
this.returnType.resolvedType = this.binding.returnType;
// record the return type binding
}
- // look if the name of the method is correct
- if (binding != null && isTypeUseDeprecated(binding.returnType, scope))
- scope.problemReporter().deprecatedType(binding.returnType, returnType);
-
// check if method with constructor name
if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
scope.problemReporter().methodWithConstructorName(this);
}
+ // check @Override annotation
+ if (this.binding != null
+ && (this.binding.tagBits & TagBits.AnnotationOverride) != 0
+ && (this.binding.modifiers & AccOverriding) == 0) {
+ scope.problemReporter().methodMustOverride(this);
+ }
+
// by grammatical construction, interface methods are always abstract
- if (!scope.enclosingSourceType().isInterface()){
-
- // if a method has an semicolon body and is not declared as abstract==>error
- // native methods may have a semicolon body
- if ((modifiers & AccSemicolonBody) != 0) {
- if ((modifiers & AccNative) == 0)
- if ((modifiers & AccAbstract) == 0)
- scope.problemReporter().methodNeedBody(this);
- } else {
- // the method HAS a body --> abstract native modifiers are forbiden
- if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
- scope.problemReporter().methodNeedingNoBody(this);
- }
+ switch (scope.referenceType().kind()) {
+ case IGenericType.ENUM_DECL :
+ if (this.selector == TypeConstants.VALUES) break;
+ if (this.selector == TypeConstants.VALUEOF) break;
+ case IGenericType.CLASS_DECL :
+ // if a method has an semicolon body and is not declared as abstract==>error
+ // native methods may have a semicolon body
+ if ((modifiers & AccSemicolonBody) != 0) {
+ if ((modifiers & AccNative) == 0)
+ if ((modifiers & AccAbstract) == 0)
+ scope.problemReporter().methodNeedBody(this);
+ } else {
+ // the method HAS a body --> abstract native modifiers are forbiden
+ if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
+ scope.problemReporter().methodNeedingNoBody(this);
+ }
}
super.resolveStatements();
}
@@ -142,6 +165,17 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
ClassScope classScope) {
if (visitor.visit(this, classScope)) {
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ if (this.typeParameters != null) {
+ int typeParametersLength = this.typeParameters.length;
+ for (int i = 0; i < typeParametersLength; i++) {
+ this.typeParameters[i].traverse(visitor, scope);
+ }
+ }
if (returnType != null)
returnType.traverse(visitor, scope);
if (arguments != null) {
@@ -162,4 +196,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
}
visitor.endVisit(this, classScope);
}
+ public TypeParameter[] typeParameters() {
+ return this.typeParameters;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/src/org/eclipse/jdt/internal/compiler/ast/NameReference.java
index 98a3f30..c48432f 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/NameReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/NameReference.java
@@ -12,11 +12,10 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.lookup.*;
-public abstract class NameReference extends Reference implements InvocationSite, BindingIds {
+public abstract class NameReference extends Reference implements InvocationSite {
public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
- public TypeBinding receiverType; // raw receiver type
public TypeBinding actualReceiverType; // modified receiver type - actual one according to namelookup
//the error printing
@@ -28,7 +27,7 @@ public abstract class NameReference extends Reference implements InvocationSite,
//no changeClass in java.
public NameReference() {
super();
- bits |= TYPE | VARIABLE; // restrictiveFlag
+ bits |= Binding.TYPE | Binding.VARIABLE; // restrictiveFlag
}
public FieldBinding fieldBinding() {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java
new file mode 100644
index 0000000..d8a720e
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/NormalAnnotation.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Normal annotation node
+ */
+public class NormalAnnotation extends Annotation {
+
+ public MemberValuePair[] memberValuePairs;
+
+ public NormalAnnotation(TypeReference type, int sourceStart) {
+ this.type = type;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = type.sourceEnd;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+ */
+ public MemberValuePair[] memberValuePairs() {
+ return this.memberValuePairs == null ? NoValuePairs : this.memberValuePairs;
+ }
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ super.printExpression(indent, output);
+ output.append('(');
+ if (this.memberValuePairs != null) {
+ for (int i = 0, max = this.memberValuePairs.length; i < max; i++) {
+ if (i > 0) {
+ output.append(',');
+ }
+ this.memberValuePairs[i].print(indent, output);
+ }
+ }
+ output.append(')');
+ return output;
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.memberValuePairs != null) {
+ int memberValuePairsLength = this.memberValuePairs.length;
+ for (int i = 0; i < memberValuePairsLength; i++)
+ this.memberValuePairs[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+ public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.memberValuePairs != null) {
+ int memberValuePairsLength = this.memberValuePairs.length;
+ for (int i = 0; i < memberValuePairsLength; i++)
+ this.memberValuePairs[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
index d79b252..ea507f3 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class NullLiteral extends MagicLiteral {
@@ -37,14 +38,20 @@ public class NullLiteral extends MagicLiteral {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
+ if (valueRequired) {
codeStream.aconst_null();
+ codeStream.generateImplicitConversion(this.implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public TypeBinding literalType(BlockScope scope) {
return NullBinding;
}
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.NULL;
+ }
+
/**
*
*/
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
index 4574e0b..7ea85eb 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+
public abstract class OperatorExpression extends Expression implements OperatorIds {
public static int[][] OperatorSignatures = new int[NumberOfTables][];
@@ -66,10 +68,10 @@ public abstract class OperatorExpression extends Expression implements OperatorI
case T_float : return "100.0f"; //$NON-NLS-1$
case T_int : return "1"; //$NON-NLS-1$
case T_long : return "7L"; //$NON-NLS-1$
- case T_String : return "\"hello-world\""; //$NON-NLS-1$
+ case T_JavaLangString : return "\"hello-world\""; //$NON-NLS-1$
case T_null : return "null"; //$NON-NLS-1$
case T_short : return "((short) 5)"; //$NON-NLS-1$
- case T_Object : return "null";} //$NON-NLS-1$
+ case T_JavaLangObject : return "null";} //$NON-NLS-1$
return "";} //$NON-NLS-1$
public final String type(int code){
@@ -81,10 +83,10 @@ public abstract class OperatorExpression extends Expression implements OperatorI
case T_float : return "f"; //$NON-NLS-1$
case T_int : return "i"; //$NON-NLS-1$
case T_long : return "l"; //$NON-NLS-1$
- case T_String : return "str"; //$NON-NLS-1$
+ case T_JavaLangString : return "str"; //$NON-NLS-1$
case T_null : return "null"; //$NON-NLS-1$
case T_short : return "s"; //$NON-NLS-1$
- case T_Object : return "obj";} //$NON-NLS-1$
+ case T_JavaLangObject : return "obj";} //$NON-NLS-1$
return "xxx";} //$NON-NLS-1$
public final String operator(int operator){
@@ -122,7 +124,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
"\t\t//method automatically generated by\n"+ //$NON-NLS-1$
"\t\t//org.eclipse.jdt.internal.compiler.ast.OperatorExpression.generateTableTestCase();\n"+ //$NON-NLS-1$
- "\t\tString str0;\t String str\t= "+decode.constant(T_String)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+ "\t\tString str0;\t String str\t= "+decode.constant(T_JavaLangString)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\t\tint i0;\t int i\t= "+decode.constant(T_int)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\t\tboolean z0;\t boolean z\t= "+decode.constant(T_boolean)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\t\tchar c0; \t char c\t= "+decode.constant(T_char)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
@@ -131,7 +133,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
"\t\tbyte b0; \t byte b\t= "+decode.constant(T_byte)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\t\tshort s0; \t short s\t= "+decode.constant(T_short)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\t\tlong l0; \t long l\t= "+decode.constant(T_long)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
- "\t\tObject obj0; \t Object obj\t= "+decode.constant(T_Object)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+ "\t\tObject obj0; \t Object obj\t= "+decode.constant(T_JavaLangObject)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
"\n"; //$NON-NLS-1$
int error = 0;
@@ -150,8 +152,8 @@ public abstract class OperatorExpression extends Expression implements OperatorI
{ s += "\t\t"+decode.type(result)+"0"+" = "+decode.type(left); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
s += " "+decode.operator(operator)+" "+decode.type(right)+";\n"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
- String begin = result == T_String ? "\t\tif (! " : "\t\tif ( "; //$NON-NLS-2$ //$NON-NLS-1$
- String test = result == T_String ? ".equals(" : " != ("; //$NON-NLS-2$ //$NON-NLS-1$
+ String begin = result == T_JavaLangString ? "\t\tif (! " : "\t\tif ( "; //$NON-NLS-2$ //$NON-NLS-1$
+ String test = result == T_JavaLangString ? ".equals(" : " != ("; //$NON-NLS-2$ //$NON-NLS-1$
s += begin +decode.type(result)+"0"+test //$NON-NLS-1$
+decode.constant(left)+" " //$NON-NLS-1$
+decode.operator(operator)+" " //$NON-NLS-1$
@@ -167,7 +169,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
public static final int[] get_AND(){
- //the code is an int
+ //the code is an int, only 20 bits are used, see below.
// (cast) left Op (cast) rigth --> result
// 0000 0000 0000 0000 0000
// <<16 <<12 <<8 <<4
@@ -649,34 +651,34 @@ public abstract class OperatorExpression extends Expression implements OperatorI
// table[(T_String<<4)+T_long] = T_undefined;
// table[(T_String<<4)+T_short] = T_undefined;
// table[(T_String<<4)+T_void] = T_undefined;
- table[(T_String<<4)+T_String] = /*String2Object String2Object*/
- (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
- table[(T_String<<4)+T_Object] = /*String2Object Object2Object*/
- (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+ table[(T_JavaLangString<<4)+T_JavaLangString] = /*String2Object String2Object*/
+ (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+ table[(T_JavaLangString<<4)+T_JavaLangObject] = /*String2Object Object2Object*/
+ (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean;
// table[(T_String<<4)+T_double] = T_undefined;
// table[(T_String<<4)+T_float] = T_undefined;
// table[(T_String<<4)+T_boolean] = T_undefined;
// table[(T_String<<4)+T_char] = T_undefined;
// table[(T_String<<4)+T_int] = T_undefined;
- table[(T_String<<4)+T_null] = /*Object2String null2Object */
- (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+ table[(T_JavaLangString<<4)+T_null] = /*Object2String null2Object */
+ (T_JavaLangObject<<16)+(T_JavaLangString<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
// table[(T_Object<<4)+T_undefined] = T_undefined;
// table[(T_Object<<4)+T_byte] = T_undefined;
// table[(T_Object<<4)+T_long] = T_undefined;
// table[(T_Object<<4)+T_short] = T_undefined;
// table[(T_Object<<4)+T_void] = T_undefined;
- table[(T_Object<<4)+T_String] = /*Object2Object String2Object*/
- (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
- table[(T_Object<<4)+T_Object] = /*Object2Object Object2Object*/
- (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+ table[(T_JavaLangObject<<4)+T_JavaLangString] = /*Object2Object String2Object*/
+ (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+ table[(T_JavaLangObject<<4)+T_JavaLangObject] = /*Object2Object Object2Object*/
+ (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean;
// table[(T_Object<<4)+T_double] = T_undefined;
// table[(T_Object<<4)+T_float] = T_undefined;
// table[(T_Object<<4)+T_boolean] = T_undefined;
// table[(T_Object<<4)+T_char] = T_undefined;
// table[(T_Object<<4)+T_int] = T_undefined;
- table[(T_Object<<4)+T_null] = /*Object2Object null2Object*/
- (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+ table[(T_JavaLangObject<<4)+T_null] = /*Object2Object null2Object*/
+ (T_JavaLangObject<<16)+(T_JavaLangObject<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
// table[(T_double<<4)+T_undefined] = T_undefined;
table[(T_double<<4)+T_byte] = (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
@@ -753,17 +755,17 @@ public abstract class OperatorExpression extends Expression implements OperatorI
// table[(T_null<<4)+T_long] = T_undefined;
// table[(T_null<<4)+T_short] = T_undefined;
// table[(T_null<<4)+T_void] = T_undefined;
- table[(T_null<<4)+T_String] = /*null2Object String2Object*/
- (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
- table[(T_null<<4)+T_Object] = /*null2Object Object2Object*/
- (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+ table[(T_null<<4)+T_JavaLangString] = /*null2Object String2Object*/
+ (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_JavaLangString<<4)+T_boolean;
+ table[(T_null<<4)+T_JavaLangObject] = /*null2Object Object2Object*/
+ (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_JavaLangObject<<4)+T_boolean;
// table[(T_null<<4)+T_double] = T_undefined;
// table[(T_null<<4)+T_float] = T_undefined;
// table[(T_null<<4)+T_boolean] = T_undefined;
// table[(T_null<<4)+T_char] = T_undefined;
// table[(T_null<<4)+T_int] = T_undefined;
table[(T_null<<4)+T_null] = /*null2Object null2Object*/
- (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+ (T_JavaLangObject<<16)+(T_null<<12)+(T_JavaLangObject<<8)+(T_null<<4)+T_boolean;
return table;
}
@@ -1200,30 +1202,30 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table = (int[]) get_PLUS().clone();
// customization
- table[(T_String<<4)+T_byte] = T_undefined;
- table[(T_String<<4)+T_long] = T_undefined;
- table[(T_String<<4)+T_short] = T_undefined;
- table[(T_String<<4)+T_void] = T_undefined;
- table[(T_String<<4)+T_String] = T_undefined;
- table[(T_String<<4)+T_Object] = T_undefined;
- table[(T_String<<4)+T_double] = T_undefined;
- table[(T_String<<4)+T_float] = T_undefined;
- table[(T_String<<4)+T_boolean] = T_undefined;
- table[(T_String<<4)+T_char] = T_undefined;
- table[(T_String<<4)+T_int] = T_undefined;
- table[(T_String<<4)+T_null] = T_undefined;
-
- table[(T_byte<<4) +T_String] = T_undefined;
- table[(T_long<<4) +T_String] = T_undefined;
- table[(T_short<<4) +T_String] = T_undefined;
- table[(T_void<<4) +T_String] = T_undefined;
- table[(T_Object<<4) +T_String] = T_undefined;
- table[(T_double<<4) +T_String] = T_undefined;
- table[(T_float<<4) +T_String] = T_undefined;
- table[(T_boolean<<4)+T_String] = T_undefined;
- table[(T_char<<4) +T_String] = T_undefined;
- table[(T_int<<4) +T_String] = T_undefined;
- table[(T_null<<4) +T_String] = T_undefined;
+ table[(T_JavaLangString<<4)+T_byte] = T_undefined;
+ table[(T_JavaLangString<<4)+T_long] = T_undefined;
+ table[(T_JavaLangString<<4)+T_short] = T_undefined;
+ table[(T_JavaLangString<<4)+T_void] = T_undefined;
+ table[(T_JavaLangString<<4)+T_JavaLangString] = T_undefined;
+ table[(T_JavaLangString<<4)+T_JavaLangObject] = T_undefined;
+ table[(T_JavaLangString<<4)+T_double] = T_undefined;
+ table[(T_JavaLangString<<4)+T_float] = T_undefined;
+ table[(T_JavaLangString<<4)+T_boolean] = T_undefined;
+ table[(T_JavaLangString<<4)+T_char] = T_undefined;
+ table[(T_JavaLangString<<4)+T_int] = T_undefined;
+ table[(T_JavaLangString<<4)+T_null] = T_undefined;
+
+ table[(T_byte<<4) +T_JavaLangString] = T_undefined;
+ table[(T_long<<4) +T_JavaLangString] = T_undefined;
+ table[(T_short<<4) +T_JavaLangString] = T_undefined;
+ table[(T_void<<4) +T_JavaLangString] = T_undefined;
+ table[(T_JavaLangObject<<4) +T_JavaLangString] = T_undefined;
+ table[(T_double<<4) +T_JavaLangString] = T_undefined;
+ table[(T_float<<4) +T_JavaLangString] = T_undefined;
+ table[(T_boolean<<4)+T_JavaLangString] = T_undefined;
+ table[(T_char<<4) +T_JavaLangString] = T_undefined;
+ table[(T_int<<4) +T_JavaLangString] = T_undefined;
+ table[(T_null<<4) +T_JavaLangString] = T_undefined;
table[(T_null<<4) +T_null] = T_undefined;
@@ -1292,7 +1294,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_byte<<4)+T_long] = (Byte2Long<<12)+(Long2Long<<4)+T_long;
table[(T_byte<<4)+T_short] = (Byte2Int<<12)+(Short2Int<<4)+T_int;
// table[(T_byte<<4)+T_void] = T_undefined;
- table[(T_byte<<4)+T_String] = (Byte2Byte<<12)+(String2String<<4)+T_String;
+ table[(T_byte<<4)+T_JavaLangString] = (Byte2Byte<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_byte<<4)+T_Object] = T_undefined;
table[(T_byte<<4)+T_double] = (Byte2Double<<12)+(Double2Double<<4)+T_double;
table[(T_byte<<4)+T_float] = (Byte2Float<<12)+(Float2Float<<4)+T_float;
@@ -1306,7 +1308,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_long<<4)+T_long] = (Long2Long<<12)+(Long2Long<<4)+T_long;
table[(T_long<<4)+T_short] = (Long2Long<<12)+(Short2Long<<4)+T_long;
// table[(T_long<<4)+T_void] = T_undefined;
- table[(T_long<<4)+T_String] = (Long2Long<<12)+(String2String<<4)+T_String;
+ table[(T_long<<4)+T_JavaLangString] = (Long2Long<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_long<<4)+T_Object] = T_undefined;
table[(T_long<<4)+T_double] = (Long2Double<<12)+(Double2Double<<4)+T_double;
table[(T_long<<4)+T_float] = (Long2Float<<12)+(Float2Float<<4)+T_float;
@@ -1320,7 +1322,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_short<<4)+T_long] = (Short2Long<<12)+(Long2Long<<4)+T_long;
table[(T_short<<4)+T_short] = (Short2Int<<12)+(Short2Int<<4)+T_int;
// table[(T_short<<4)+T_void] = T_undefined;
- table[(T_short<<4)+T_String] = (Short2Short<<12)+(String2String<<4)+T_String;
+ table[(T_short<<4)+T_JavaLangString] = (Short2Short<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_short<<4)+T_Object] = T_undefined;
table[(T_short<<4)+T_double] = (Short2Double<<12)+(Double2Double<<4)+T_double;
table[(T_short<<4)+T_float] = (Short2Float<<12)+(Float2Float<<4)+T_float;
@@ -1344,25 +1346,25 @@ public abstract class OperatorExpression extends Expression implements OperatorI
// table[(T_void<<4)+T_null] = T_undefined;
// table[(T_String<<4)+T_undefined] = T_undefined;
- table[(T_String<<4)+T_byte] = (String2String<<12)+(Byte2Byte<<4)+T_String;
- table[(T_String<<4)+T_long] = (String2String<<12)+(Long2Long<<4)+T_String;
- table[(T_String<<4)+T_short] = (String2String<<12)+(Short2Short<<4)+T_String;
+ table[(T_JavaLangString<<4)+T_byte] = (String2String<<12)+(Byte2Byte<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_long] = (String2String<<12)+(Long2Long<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_short] = (String2String<<12)+(Short2Short<<4)+T_JavaLangString;
// table[(T_String<<4)+T_void] = T_undefined;
- table[(T_String<<4)+T_String] = (String2String<<12)+(String2String<<4)+T_String;
- table[(T_String<<4)+T_Object] = (String2String<<12)+(Object2Object<<4)+T_String;
- table[(T_String<<4)+T_double] = (String2String<<12)+(Double2Double<<4)+T_String;
- table[(T_String<<4)+T_float] = (String2String<<12)+(Float2Float<<4)+T_String;
- table[(T_String<<4)+T_boolean] = (String2String<<12)+(Boolean2Boolean<<4)+T_String;
- table[(T_String<<4)+T_char] = (String2String<<12)+(Char2Char<<4)+T_String;
- table[(T_String<<4)+T_int] = (String2String<<12)+(Int2Int<<4)+T_String;
- table[(T_String<<4)+T_null] = (String2String<<12)+(T_null<<8)+(T_null<<4)+T_String;
+ table[(T_JavaLangString<<4)+T_JavaLangString] = (String2String<<12)+(String2String<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_JavaLangObject] = (String2String<<12)+(Object2Object<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_double] = (String2String<<12)+(Double2Double<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_float] = (String2String<<12)+(Float2Float<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_boolean] = (String2String<<12)+(Boolean2Boolean<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_char] = (String2String<<12)+(Char2Char<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_int] = (String2String<<12)+(Int2Int<<4)+T_JavaLangString;
+ table[(T_JavaLangString<<4)+T_null] = (String2String<<12)+(T_null<<8)+(T_null<<4)+T_JavaLangString;
// table[(T_Object<<4)+T_undefined] = T_undefined;
// table[(T_Object<<4)+T_byte] = T_undefined;
// table[(T_Object<<4)+T_long] = T_undefined;
// table[(T_Object<<4)+T_short] = T_undefined;
// table[(T_Object<<4)+T_void] = T_undefined;
- table[(T_Object<<4)+T_String] = (Object2Object<<12)+(String2String<<4)+T_String;
+ table[(T_JavaLangObject<<4)+T_JavaLangString] = (Object2Object<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_Object<<4)+T_Object] = T_undefined;
// table[(T_Object<<4)+T_double] = T_undefined;
// table[(T_Object<<4)+T_float] = T_undefined;
@@ -1376,7 +1378,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_double<<4)+T_long] = (Double2Double<<12)+(Long2Double<<4)+T_double;
table[(T_double<<4)+T_short] = (Double2Double<<12)+(Short2Double<<4)+T_double;
// table[(T_double<<4)+T_void] = T_undefined;
- table[(T_double<<4)+T_String] = (Double2Double<<12)+(String2String<<4)+T_String;
+ table[(T_double<<4)+T_JavaLangString] = (Double2Double<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_double<<4)+T_Object] = T_undefined;
table[(T_double<<4)+T_double] = (Double2Double<<12)+(Double2Double<<4)+T_double;
table[(T_double<<4)+T_float] = (Double2Double<<12)+(Float2Double<<4)+T_double;
@@ -1390,7 +1392,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_float<<4)+T_long] = (Float2Float<<12)+(Long2Float<<4)+T_float;
table[(T_float<<4)+T_short] = (Float2Float<<12)+(Short2Float<<4)+T_float;
// table[(T_float<<4)+T_void] = T_undefined;
- table[(T_float<<4)+T_String] = (Float2Float<<12)+(String2String<<4)+T_String;
+ table[(T_float<<4)+T_JavaLangString] = (Float2Float<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_float<<4)+T_Object] = T_undefined;
table[(T_float<<4)+T_double] = (Float2Double<<12)+(Double2Double<<4)+T_double;
table[(T_float<<4)+T_float] = (Float2Float<<12)+(Float2Float<<4)+T_float;
@@ -1404,7 +1406,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
// table[(T_boolean<<4)+T_long] = T_undefined;
// table[(T_boolean<<4)+T_short] = T_undefined;
// table[(T_boolean<<4)+T_void] = T_undefined;
- table[(T_boolean<<4)+T_String] = (Boolean2Boolean<<12)+(String2String<<4)+T_String;
+ table[(T_boolean<<4)+T_JavaLangString] = (Boolean2Boolean<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_boolean<<4)+T_Object] = T_undefined;
// table[(T_boolean<<4)+T_double] = T_undefined;
// table[(T_boolean<<4)+T_float] = T_undefined;
@@ -1418,7 +1420,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_char<<4)+T_long] = (Char2Long<<12)+(Long2Long<<4)+T_long;
table[(T_char<<4)+T_short] = (Char2Int<<12)+(Short2Int<<4)+T_int;
// table[(T_char<<4)+T_void] = T_undefined;
- table[(T_char<<4)+T_String] = (Char2Char<<12)+(String2String<<4)+T_String;
+ table[(T_char<<4)+T_JavaLangString] = (Char2Char<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_char<<4)+T_Object] = T_undefined;
table[(T_char<<4)+T_double] = (Char2Double<<12)+(Double2Double<<4)+T_double;
table[(T_char<<4)+T_float] = (Char2Float<<12)+(Float2Float<<4)+T_float;
@@ -1432,7 +1434,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
table[(T_int<<4)+T_long] = (Int2Long<<12)+(Long2Long<<4)+T_long;
table[(T_int<<4)+T_short] = (Int2Int<<12)+(Short2Int<<4)+T_int;
// table[(T_int<<4)+T_void] = T_undefined;
- table[(T_int<<4)+T_String] = (Int2Int<<12)+(String2String<<4)+T_String;
+ table[(T_int<<4)+T_JavaLangString] = (Int2Int<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_int<<4)+T_Object] = T_undefined;
table[(T_int<<4)+T_double] = (Int2Double<<12)+(Double2Double<<4)+T_double;
table[(T_int<<4)+T_float] = (Int2Float<<12)+(Float2Float<<4)+T_float;
@@ -1446,7 +1448,7 @@ public abstract class OperatorExpression extends Expression implements OperatorI
// table[(T_null<<4)+T_long] = T_undefined;
// table[(T_null<<4)+T_short] = T_undefined;
// table[(T_null<<4)+T_void] = T_undefined;
- table[(T_null<<4)+T_String] = (T_null<<16)+(T_null<<12)+(String2String<<4)+T_String;
+ table[(T_null<<4)+T_JavaLangString] = (T_null<<16)+(T_null<<12)+(String2String<<4)+T_JavaLangString;
// table[(T_null<<4)+T_Object] = T_undefined;
// table[(T_null<<4)+T_double] = T_undefined;
// table[(T_null<<4)+T_float] = T_undefined;
@@ -1554,6 +1556,10 @@ public abstract class OperatorExpression extends Expression implements OperatorI
return "unknown operator"; //$NON-NLS-1$
}
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.UNKNOWN;
+ }
+
public StringBuffer printExpression(int indent, StringBuffer output){
output.append('(');
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
new file mode 100644
index 0000000..eed5a1f
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Syntactic representation of a reference to a generic type.
+ * Note that it might also have a dimension.
+ */
+public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeReference {
+
+ public TypeReference[][] typeArguments;
+ private boolean didResolve = false;
+
+ /**
+ * @param tokens
+ * @param dim
+ * @param positions
+ */
+ public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions) {
+
+ super(tokens, dim, positions);
+ this.typeArguments = typeArguments;
+ }
+ public void checkBounds(Scope scope) {
+ if (this.resolvedType == null) return;
+
+ checkBounds(
+ (ReferenceBinding) this.resolvedType.leafComponentType(),
+ scope,
+ this.typeArguments.length - 1);
+ }
+ public void checkBounds(ReferenceBinding type, Scope scope, int index) {
+ if (type.enclosingType() != null)
+ checkBounds(type.enclosingType(), scope, index - 1);
+
+ if (type.isParameterizedType()) {
+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
+ ReferenceBinding currentType = parameterizedType.type;
+ TypeVariableBinding[] typeVariables = currentType.typeVariables();
+ TypeBinding[] argTypes = parameterizedType.arguments;
+ if (argTypes != null && typeVariables != null) { // argTypes may be null in error cases
+ for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
+ if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+ scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[index][i]);
+ }
+ }
+ }
+ public TypeReference copyDims(int dim){
+ //return a type reference copy of me with some dimensions
+ //warning : the new type ref has a null binding
+ this.dimensions = dim;
+ return this;
+ }
+
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ int length = this.tokens.length;
+ char[][] qParamName = new char[length][];
+ for (int i = 0; i < length; i++) {
+ TypeReference[] arguments = this.typeArguments[i];
+ if (arguments == null) {
+ qParamName[i] = this.tokens[i];
+ } else {
+ StringBuffer buffer = new StringBuffer(5);
+ buffer.append(this.tokens[i]);
+ buffer.append('<');
+ for (int j = 0, argLength =arguments.length; j < argLength; j++) {
+ if (j > 0) buffer.append(',');
+ buffer.append(CharOperation.concatWith(arguments[j].getParameterizedTypeName(), '.'));
+ }
+ buffer.append('>');
+ int nameLength = buffer.length();
+ qParamName[i] = new char[nameLength];
+ buffer.getChars(0, nameLength, qParamName[i], 0);
+ }
+ }
+ int dim = this.dimensions;
+ if (dim > 0) {
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ qParamName[length-1] = CharOperation.concat(qParamName[length-1], dimChars);
+ }
+ return qParamName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
+ */
+ protected TypeBinding getTypeBinding(Scope scope) {
+ return null; // not supported here - combined with resolveType(...)
+ }
+
+ /*
+ * No need to check for reference to raw type per construction
+ */
+ private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
+
+ // handle the error here
+ this.constant = NotAConstant;
+ if (this.didResolve) { // is a shared type reference which was already resolved
+ if (this.resolvedType != null && !this.resolvedType.isValidBinding())
+ return null; // already reported error
+ return this.resolvedType;
+ }
+ this.didResolve = true;
+ Binding binding = scope.getPackage(this.tokens);
+ if (binding != null && !binding.isValidBinding()) {
+ this.resolvedType = (ReferenceBinding) binding;
+ reportInvalidType(scope);
+ return null;
+ }
+
+ PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
+ boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+ boolean typeIsConsistent = true;
+ ReferenceBinding qualifiedType = null;
+ for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) {
+ findNextTypeBinding(i, scope, packageBinding);
+ if (!(this.resolvedType.isValidBinding())) {
+ reportInvalidType(scope);
+ return null;
+ }
+ ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+ if (qualifiedType == null) {
+ qualifiedType = currentType.enclosingType(); // if member type
+ if (qualifiedType != null && currentType.isStatic() && (qualifiedType.isGenericType() || qualifiedType.isParameterizedType())) {
+ qualifiedType = scope.environment().createRawType((ReferenceBinding)qualifiedType.erasure(), qualifiedType.enclosingType());
+ }
+ }
+ if (typeIsConsistent && currentType.isStatic() && qualifiedType != null && (qualifiedType.isParameterizedType() || qualifiedType.isGenericType())) {
+ scope.problemReporter().staticMemberOfParameterizedType(this, scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType));
+ typeIsConsistent = false;
+ }
+ // check generic and arity
+ TypeReference[] args = this.typeArguments[i];
+ if (args != null) {
+ int argLength = args.length;
+ TypeBinding[] argTypes = new TypeBinding[argLength];
+ boolean argHasError = false;
+ for (int j = 0; j < argLength; j++) {
+ TypeReference arg = args[j];
+ TypeBinding argType = isClassScope
+ ? arg.resolveTypeArgument((ClassScope) scope, currentType, j)
+ : arg.resolveTypeArgument((BlockScope) scope, currentType, j);
+ if (argType == null) {
+ argHasError = true;
+ } else {
+ argTypes[j] = argType;
+ }
+ }
+ if (argHasError) return null;
+// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
+ if (isClassScope)
+ if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
+ return null;
+
+ TypeVariableBinding[] typeVariables = currentType.typeVariables();
+ if (typeVariables == NoTypeVariables) { // check generic
+ scope.problemReporter().nonGenericTypeCannotBeParameterized(this, currentType, argTypes);
+ return null;
+ } else if (argLength != typeVariables.length) { // check arity
+ scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
+ return null;
+ }
+ // check parameterizing non-static member type of raw type
+ if (typeIsConsistent && !currentType.isStatic() && qualifiedType != null && qualifiedType.isRawType()) {
+ scope.problemReporter().rawMemberTypeCannotBeParameterized(
+ this, scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType), argTypes);
+ typeIsConsistent = false;
+ }
+ ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
+ // check argument type compatibility
+ if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+ for (int j = 0; j < argLength; j++)
+ if (!typeVariables[j].boundCheck(parameterizedType, argTypes[j]))
+ scope.problemReporter().typeMismatchError(argTypes[j], typeVariables[j], currentType, args[j]);
+ qualifiedType = parameterizedType;
+ } else {
+// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
+ if (isClassScope)
+ if (((ClassScope) scope).detectHierarchyCycle(currentType, this, null))
+ return null;
+ if (currentType.isGenericType()) {
+ if (typeIsConsistent && qualifiedType != null && qualifiedType.isParameterizedType()) {
+ scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType));
+ typeIsConsistent = false;
+ }
+ qualifiedType = scope.environment().createRawType(currentType, qualifiedType); // raw type
+ } else {
+ qualifiedType = (qualifiedType != null && qualifiedType.isParameterizedType())
+ ? scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType)
+ : currentType;
+ }
+ }
+ }
+ this.resolvedType = qualifiedType;
+ if (isTypeUseDeprecated(this.resolvedType, scope))
+ reportDeprecatedType(scope);
+ // array type ?
+ if (this.dimensions > 0) {
+ if (dimensions > 255)
+ scope.problemReporter().tooManyDimensions(this);
+ this.resolvedType = scope.createArrayType(this.resolvedType, dimensions);
+ }
+ return this.resolvedType;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ int length = tokens.length;
+ for (int i = 0; i < length - 1; i++) {
+ output.append(tokens[i]);
+ TypeReference[] typeArgument = typeArguments[i];
+ if (typeArgument != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeArgument.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeArgument[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArgument[max].print(0, output);
+ output.append('>');
+ }
+ output.append('.');
+ }
+ output.append(tokens[length - 1]);
+ TypeReference[] typeArgument = typeArguments[length - 1];
+ if (typeArgument != null) {
+ output.append('<');//$NON-NLS-1$
+ int max = typeArgument.length - 1;
+ for (int j = 0; j < max; j++) {
+ typeArgument[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArgument[max].print(0, output);
+ output.append('>');
+ }
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ }
+ return output;
+ }
+
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ return internalResolveType(scope, checkBounds);
+ }
+ public TypeBinding resolveType(ClassScope scope) {
+ return internalResolveType(scope, false);
+ }
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ if (this.typeArguments[i] != null) {
+ for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
+ this.typeArguments[i][j].traverse(visitor, scope);
+ }
+ }
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+ if (visitor.visit(this, scope)) {
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ if (this.typeArguments[i] != null) {
+ for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
+ this.typeArguments[i][j].traverse(visitor, scope);
+ }
+ }
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
new file mode 100644
index 0000000..8c4494f
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Syntactic representation of a reference to a generic type.
+ * Note that it might also have a dimension.
+ */
+public class ParameterizedSingleTypeReference extends ArrayTypeReference {
+
+ public TypeReference[] typeArguments;
+ private boolean didResolve = false;
+
+ public ParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, int dim, long pos){
+ super(name, dim, pos);
+ this.originalSourceEnd = this.sourceEnd;
+ this.typeArguments = typeArguments;
+ }
+ public void checkBounds(Scope scope) {
+ if (this.resolvedType == null) return;
+
+ if (this.resolvedType.leafComponentType() instanceof ParameterizedTypeBinding) {
+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this.resolvedType.leafComponentType();
+ ReferenceBinding currentType = parameterizedType.type;
+ TypeVariableBinding[] typeVariables = currentType.typeVariables();
+ TypeBinding[] argTypes = parameterizedType.arguments;
+ if (argTypes != null && typeVariables != null) { // may be null in error cases
+ for (int i = 0, argLength = typeVariables.length; i < argLength; i++)
+ if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+ scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+ }
+ }
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
+ */
+ public TypeReference copyDims(int dim) {
+ this.dimensions = dim;
+ return this;
+ }
+
+ /**
+ * @return char[][]
+ */
+ public char [][] getParameterizedTypeName(){
+ StringBuffer buffer = new StringBuffer(5);
+ buffer.append(this.token).append('<');
+ for (int i = 0, length = this.typeArguments.length; i < length; i++) {
+ if (i > 0) buffer.append(',');
+ buffer.append(CharOperation.concatWith(this.typeArguments[i].getParameterizedTypeName(), '.'));
+ }
+ buffer.append('>');
+ int nameLength = buffer.length();
+ char[] name = new char[nameLength];
+ buffer.getChars(0, nameLength, name, 0);
+ int dim = this.dimensions;
+ if (dim > 0) {
+ char[] dimChars = new char[dim*2];
+ for (int i = 0; i < dim; i++) {
+ int index = i*2;
+ dimChars[index] = '[';
+ dimChars[index+1] = ']';
+ }
+ name = CharOperation.concat(name, dimChars);
+ }
+ return new char[][]{ name };
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
+ */
+ protected TypeBinding getTypeBinding(Scope scope) {
+ return null; // not supported here - combined with resolveType(...)
+ }
+
+ /*
+ * No need to check for reference to raw type per construction
+ */
+ private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
+
+ // handle the error here
+ this.constant = NotAConstant;
+ if (this.didResolve) { // is a shared type reference which was already resolved
+ if (this.resolvedType != null && !this.resolvedType.isValidBinding())
+ return null; // already reported error
+ return this.resolvedType;
+ }
+ this.didResolve = true;
+ if (enclosingType == null) {
+ this.resolvedType = scope.getType(token);
+ if (!(this.resolvedType.isValidBinding())) {
+ reportInvalidType(scope);
+ return null;
+ }
+ enclosingType = this.resolvedType.enclosingType(); // if member type
+ if (enclosingType != null) {
+ ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+ if (currentType.isStatic() && (enclosingType.isGenericType() || enclosingType.isParameterizedType())) {
+ enclosingType = scope.environment().createRawType((ReferenceBinding)enclosingType.erasure(), enclosingType.enclosingType());
+ }
+ }
+ } else { // resolving member type (relatively to enclosingType)
+ this.resolvedType = scope.getMemberType(token, (ReferenceBinding)enclosingType.erasure());
+ if (!this.resolvedType.isValidBinding()) {
+ scope.problemReporter().invalidEnclosingType(this, this.resolvedType, enclosingType);
+ return null;
+ }
+ if (isTypeUseDeprecated(this.resolvedType, scope))
+ scope.problemReporter().deprecatedType(this.resolvedType, this);
+ }
+
+ // check generic and arity
+ boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+ ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+ int argLength = this.typeArguments.length;
+ TypeBinding[] argTypes = new TypeBinding[argLength];
+ boolean argHasError = false;
+ for (int i = 0; i < argLength; i++) {
+ TypeReference typeArgument = this.typeArguments[i];
+ TypeBinding argType = isClassScope
+ ? typeArgument.resolveTypeArgument((ClassScope) scope, currentType, i)
+ : typeArgument.resolveTypeArgument((BlockScope) scope, currentType, i);
+ if (argType == null) {
+ argHasError = true;
+ } else {
+ argTypes[i] = argType;
+ }
+ }
+ if (argHasError) return null;
+// TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0)
+ if (isClassScope)
+ if (((ClassScope) scope).detectHierarchyCycle(currentType, this, argTypes))
+ return null;
+
+ TypeVariableBinding[] typeVariables = currentType.typeVariables();
+ if (typeVariables == NoTypeVariables) { // check generic
+ scope.problemReporter().nonGenericTypeCannotBeParameterized(this, currentType, argTypes);
+ return null;
+ } else if (argLength != typeVariables.length) { // check arity
+ scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
+ return null;
+ }
+ // if generic type X is referred to as parameterized X, then answer itself
+ checkGeneric: {
+ for (int i = 0; i < argLength; i++)
+ if (typeVariables[i] != argTypes[i])
+ break checkGeneric;
+ return currentType;
+ }
+ ParameterizedTypeBinding parameterizedType = scope.createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, enclosingType);
+ // check argument type compatibility
+ if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+ for (int i = 0; i < argLength; i++)
+ if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i]))
+ scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]);
+
+ this.resolvedType = parameterizedType;
+ if (isTypeUseDeprecated(this.resolvedType, scope))
+ reportDeprecatedType(scope);
+ // array type ?
+ if (this.dimensions > 0) {
+ if (dimensions > 255)
+ scope.problemReporter().tooManyDimensions(this);
+ this.resolvedType = scope.createArrayType(parameterizedType, dimensions);
+ }
+ return this.resolvedType;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+ output.append(token);
+ output.append("<"); //$NON-NLS-1$
+ int max = typeArguments.length - 1;
+ for (int i= 0; i < max; i++) {
+ typeArguments[i].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ typeArguments[max].print(0, output);
+ output.append(">"); //$NON-NLS-1$
+ if ((this.bits & IsVarArgs) != 0) {
+ for (int i= 0 ; i < dimensions - 1; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ output.append("..."); //$NON-NLS-1$
+ } else {
+ for (int i= 0 ; i < dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ }
+ return output;
+ }
+
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ return internalResolveType(scope, null, checkBounds);
+ }
+
+ public TypeBinding resolveType(ClassScope scope) {
+ return internalResolveType(scope, null, false /*no bounds check in classScope*/);
+ }
+
+ public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+ return internalResolveType(scope, enclosingType, true/*check bounds*/);
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ this.typeArguments[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+ if (visitor.visit(this, scope)) {
+ for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+ this.typeArguments[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index af7dd02..289eca2 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -16,7 +16,10 @@ import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
/**
- * Variation on allocation, where can be specified an enclosing instance and an anonymous type
+ * Variation on allocation, where can optionally be specified any of:
+ * - leading enclosing instance
+ * - trailing anonymous type
+ * - generic type arguments for generic constructor invocation
*/
public class QualifiedAllocationExpression extends AllocationExpression {
@@ -31,6 +34,7 @@ public class QualifiedAllocationExpression extends AllocationExpression {
public QualifiedAllocationExpression(TypeDeclaration anonymousType) {
this.anonymousType = anonymousType;
+ anonymousType.allocation = this;
}
public FlowInfo analyseCode(
@@ -44,8 +48,9 @@ public class QualifiedAllocationExpression extends AllocationExpression {
}
// check captured variables are initialized in current context (26134)
+ ReferenceBinding allocatedType = this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding;
checkCapturedLocalInitializationIfNecessary(
- this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding,
+ (ReferenceBinding) allocatedType.erasure(),
currentScope,
flowInfo);
@@ -87,14 +92,19 @@ public class QualifiedAllocationExpression extends AllocationExpression {
boolean valueRequired) {
int pc = codeStream.position;
- ReferenceBinding allocatedType = binding.declaringClass;
+ ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
codeStream.new_(allocatedType);
if (valueRequired) {
codeStream.dup();
}
// better highlight for allocation: display the type individually
- codeStream.recordPositionsFrom(pc, type.sourceStart);
-
+ if (this.type != null) { // null for enum constant body
+ codeStream.recordPositionsFrom(pc, this.type.sourceStart);
+ } else {
+ // push enum constant name and ordinal
+ codeStream.ldc(String.valueOf(enumConstant.name));
+ codeStream.generateInlinedValue(enumConstant.binding.id);
+ }
// handling innerclass instance allocation - enclosing instance arguments
if (allocatedType.isNestedType()) {
codeStream.generateSyntheticEnclosingInstanceValues(
@@ -104,11 +114,7 @@ public class QualifiedAllocationExpression extends AllocationExpression {
this);
}
// generate the arguments for constructor
- if (arguments != null) {
- for (int i = 0, count = arguments.length; i < count; i++) {
- arguments[i].generateCode(currentScope, codeStream, true);
- }
- }
+ generateArguments(binding, arguments, currentScope, codeStream);
// handling innerclass instance allocation - outer local arguments
if (allocatedType.isNestedType()) {
codeStream.generateSyntheticOuterArgumentValues(
@@ -119,17 +125,18 @@ public class QualifiedAllocationExpression extends AllocationExpression {
// invoke constructor
if (syntheticAccessor == null) {
- codeStream.invokespecial(binding);
+ codeStream.invokespecial(this.codegenBinding);
} else {
// synthetic accessor got some extra arguments appended to its signature, which need values
for (int i = 0,
- max = syntheticAccessor.parameters.length - binding.parameters.length;
+ max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length;
i < max;
i++) {
codeStream.aconst_null();
}
codeStream.invokespecial(syntheticAccessor);
}
+ codeStream.generateImplicitConversion(this.implicitConversion);
codeStream.recordPositionsFrom(pc, this.sourceStart);
if (anonymousType != null) {
@@ -153,17 +160,17 @@ public class QualifiedAllocationExpression extends AllocationExpression {
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
if (!flowInfo.isReachable()) return;
- ReferenceBinding allocatedType;
+ ReferenceBinding allocatedTypeErasure = (ReferenceBinding) binding.declaringClass.erasure();
// perform some emulation work in case there is some and we are inside a local type only
- if ((allocatedType = binding.declaringClass).isNestedType()
+ if (allocatedTypeErasure.isNestedType()
&& currentScope.enclosingSourceType().isLocalType()) {
- if (allocatedType.isLocalType()) {
- ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, enclosingInstance != null);
+ if (allocatedTypeErasure.isLocalType()) {
+ ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, enclosingInstance != null);
} else {
// locally propagate, since we already now the desired shape for sure
- currentScope.propagateInnerEmulation(allocatedType, enclosingInstance != null);
+ currentScope.propagateInnerEmulation(allocatedTypeErasure, enclosingInstance != null);
}
}
}
@@ -182,17 +189,14 @@ public class QualifiedAllocationExpression extends AllocationExpression {
public TypeBinding resolveType(BlockScope scope) {
// added for code assist...cannot occur with 'normal' code
- if (anonymousType == null && enclosingInstance == null) {
+ if (this.anonymousType == null && this.enclosingInstance == null) {
return super.resolveType(scope);
}
// Propagate the type checking to the arguments, and checks if the constructor is defined.
// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
// ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
- // ==> by construction, when there is an enclosing instance the typename may NOT be qualified
- // ==> therefore by construction the type is always a SingleTypeReferenceType instead of being either
- // sometime a SingleTypeReference and sometime a QualifedTypeReference
-
+
constant = NotAConstant;
TypeBinding enclosingInstanceType = null;
TypeBinding receiverType = null;
@@ -212,22 +216,42 @@ public class QualifiedAllocationExpression extends AllocationExpression {
enclosingInstanceType,
enclosingInstance);
hasError = true;
+ } else if (type instanceof QualifiedTypeReference) {
+ scope.problemReporter().illegalUsageOfQualifiedTypeReference((QualifiedTypeReference)type);
+ hasError = true;
} else {
receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
if (receiverType != null && enclosingInstanceContainsCast) {
- CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
+ CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
}
}
} else {
- receiverType = type.resolveType(scope);
+ if (this.type == null) {
+ // initialization of an enum constant
+ receiverType = scope.enclosingSourceType();
+ } else {
+ receiverType = this.type.resolveType(scope, true /* check bounds*/);
+ }
}
if (receiverType == null) {
hasError = true;
} else if (((ReferenceBinding) receiverType).isFinal() && this.anonymousType != null) {
- scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
+ if (!receiverType.isEnum()) {
+ scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
+ }
hasError = true;
}
-
+ // resolve type arguments (for generic constructor call)
+ if (this.typeArguments != null) {
+ int length = this.typeArguments.length;
+ this.genericTypeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ TypeBinding argType = this.typeArguments[i].resolveType(scope, true /* check bounds*/);
+ if (argType == null) return null; // error already reported
+ this.genericTypeArguments[i] = argType;
+ }
+ }
+
// will check for null after args are resolved
TypeBinding[] argumentTypes = NoParameters;
if (arguments != null) {
@@ -246,7 +270,6 @@ public class QualifiedAllocationExpression extends AllocationExpression {
}
// limit of fault-tolerance
if (hasError) return this.resolvedType = receiverType;
-
if (this.anonymousType == null) {
// qualified allocation with no anonymous type
ReferenceBinding allocationType = (ReferenceBinding) receiverType;
@@ -258,14 +281,8 @@ public class QualifiedAllocationExpression extends AllocationExpression {
if (isMethodUseDeprecated(binding, scope)) {
scope.problemReporter().deprecatedMethod(this.binding, this);
}
- if (arguments != null) {
- for (int i = 0; i < arguments.length; i++) {
- arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
- }
- if (argsContainCast) {
- CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
- }
- }
+ if (this.arguments != null)
+ checkInvocationArguments(scope, null, allocationType, binding, this.arguments, argumentTypes, argsContainCast, this);
} else {
if (this.binding.declaringClass == null) {
this.binding.declaringClass = allocationType;
@@ -276,16 +293,21 @@ public class QualifiedAllocationExpression extends AllocationExpression {
// The enclosing instance must be compatible with the innermost enclosing type
ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
- if (enclosingInstanceType.isCompatibleWith(expectedType)) {
+ if (expectedType != enclosingInstanceType) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType);
+ if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) {
+ enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType);
return receiverType;
}
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
- this.enclosingInstance,
- enclosingInstanceType,
- expectedType);
+ scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance);
return this.resolvedType = receiverType;
}
+ if (receiverType.isTypeVariable()) {
+ receiverType = new ProblemReferenceBinding(receiverType.sourceName(), (ReferenceBinding)receiverType, ProblemReasons.IllegalSuperTypeVariable);
+ scope.problemReporter().invalidType(this, receiverType);
+ return null;
+ }
// anonymous type scenario
// an anonymous class inherits from java.lang.Object when declared "after" an interface
this.superTypeBinding = receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType;
@@ -293,6 +315,9 @@ public class QualifiedAllocationExpression extends AllocationExpression {
scope.addAnonymousType(this.anonymousType, (ReferenceBinding) receiverType);
this.anonymousType.resolve(scope);
+ if ((receiverType.tagBits & TagBits.HasDirectWildcard) != 0) {
+ scope.problemReporter().superTypeCannotUseWildcard(anonymousType.binding, this.type, receiverType);
+ }
// find anonymous super constructor
MethodBinding inheritedBinding = scope.getConstructor(this.superTypeBinding, argumentTypes, this);
if (!inheritedBinding.isValidBinding()) {
@@ -307,24 +332,17 @@ public class QualifiedAllocationExpression extends AllocationExpression {
if (targetEnclosing == null) {
scope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, (ReferenceBinding)receiverType);
return this.resolvedType = anonymousType.binding;
- } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing)) {
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(enclosingInstance, enclosingInstanceType, targetEnclosing);
+ } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
+ scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, enclosingInstance);
return this.resolvedType = anonymousType.binding;
}
+ enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
}
+ if (this.arguments != null)
+ checkInvocationArguments(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this);
- // this promotion has to be done somewhere: here or inside the constructor of the
- // anonymous class. We do it here while the constructor of the inner is then easier.
- if (arguments != null) {
- for (int i = 0; i < arguments.length; i++) {
- arguments[i].implicitWidening(inheritedBinding.parameters[i], argumentTypes[i]);
- }
- if (argsContainCast) {
- CastExpression.checkNeedForArgumentCasts(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, this);
- }
- }
// Update the anonymous inner class : superclass, interface
- binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
+ binding = anonymousType.createDefaultConstructorWithBinding(inheritedBinding);
return this.resolvedType = anonymousType.binding; // 1.2 change
}
@@ -333,7 +351,13 @@ public class QualifiedAllocationExpression extends AllocationExpression {
if (visitor.visit(this, scope)) {
if (enclosingInstance != null)
enclosingInstance.traverse(visitor, scope);
- type.traverse(visitor, scope);
+ if (this.typeArguments != null) {
+ for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
+ this.typeArguments[i].traverse(visitor, scope);
+ }
+ }
+ if (this.type != null) // case of enum constant
+ this.type.traverse(visitor, scope);
if (arguments != null) {
int argumentsLength = arguments.length;
for (int i = 0; i < argumentsLength; i++)
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index 8afa15a..154a32b 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -25,9 +25,11 @@ public class QualifiedNameReference extends NameReference {
public FieldBinding[] otherBindings, otherCodegenBindings;
int[] otherDepths;
public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
- SyntheticAccessMethodBinding syntheticWriteAccessor;
- SyntheticAccessMethodBinding[] syntheticReadAccessors;
- protected FieldBinding lastFieldBinding;
+ SyntheticMethodBinding syntheticWriteAccessor;
+ SyntheticMethodBinding[] syntheticReadAccessors;
+ public TypeBinding genericCast;
+ public TypeBinding[] otherGenericCasts;
+
public QualifiedNameReference(
char[][] sources,
long[] positions,
@@ -39,6 +41,7 @@ public class QualifiedNameReference extends NameReference {
this.sourceStart = sourceStart;
this.sourceEnd = sourceEnd;
}
+
public FlowInfo analyseAssignment(
BlockScope currentScope,
FlowContext flowContext,
@@ -49,11 +52,12 @@ public class QualifiedNameReference extends NameReference {
// determine the rank until which we now we do not need any actual value for the field access
int otherBindingsCount = otherBindings == null ? 0 : otherBindings.length;
boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
+ FieldBinding lastFieldBinding = null;
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // reading a field
+ case Binding.FIELD : // reading a field
lastFieldBinding = (FieldBinding) binding;
if (needValue) {
- manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
} // check if final blank field
if (lastFieldBinding.isBlankFinal()
&& this.otherBindings != null // the last field binding is only assigned
@@ -65,7 +69,7 @@ public class QualifiedNameReference extends NameReference {
}
}
break;
- case LOCAL :
+ case Binding.LOCAL :
// first binding is a local variable
LocalVariableBinding localBinding;
if (!flowInfo
@@ -77,6 +81,7 @@ public class QualifiedNameReference extends NameReference {
} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
localBinding.useFlag = LocalVariableBinding.FAKE_USED;
}
+ this.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
}
if (needValue) {
@@ -89,7 +94,7 @@ public class QualifiedNameReference extends NameReference {
lastFieldBinding = otherBindings[i];
needValue = !otherBindings[i+1].isStatic();
if (needValue) {
- manageSyntheticReadAccessIfNecessary(
+ manageSyntheticAccessIfNecessary(
currentScope,
lastFieldBinding,
i == 0
@@ -119,7 +124,7 @@ public class QualifiedNameReference extends NameReference {
} else {
lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
}
- manageSyntheticReadAccessIfNecessary(
+ manageSyntheticAccessIfNecessary(
currentScope,
lastFieldBinding,
lastReceiverType,
@@ -166,7 +171,7 @@ public class QualifiedNameReference extends NameReference {
} else {
lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
}
- manageSyntheticWriteAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
return flowInfo;
}
@@ -190,9 +195,9 @@ public class QualifiedNameReference extends NameReference {
boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic();
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // reading a field
+ case Binding.FIELD : // reading a field
if (needValue) {
- manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
}
// check if reading a final blank field
FieldBinding fieldBinding;
@@ -204,7 +209,7 @@ public class QualifiedNameReference extends NameReference {
currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
}
break;
- case LOCAL : // reading a local variable
+ case Binding.LOCAL : // reading a local variable
LocalVariableBinding localBinding;
if (!flowInfo
.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
@@ -215,6 +220,7 @@ public class QualifiedNameReference extends NameReference {
} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
localBinding.useFlag = LocalVariableBinding.FAKE_USED;
}
+ this.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
}
if (needValue) {
manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
@@ -224,12 +230,10 @@ public class QualifiedNameReference extends NameReference {
for (int i = 0; i < otherBindingsCount; i++) {
needValue = i < otherBindingsCount-1 ? !otherBindings[i+1].isStatic() : valueRequired;
if (needValue) {
- manageSyntheticReadAccessIfNecessary(
+ manageSyntheticAccessIfNecessary(
currentScope,
otherBindings[i],
- i == 0
- ? ((VariableBinding)binding).type
- : otherBindings[i-1].type,
+ i == 0 ? ((VariableBinding)binding).type : otherBindings[i-1].type,
i + 1,
flowInfo);
}
@@ -252,16 +256,45 @@ public class QualifiedNameReference extends NameReference {
scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
}
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= FIELD;
+ bits |= Binding.FIELD;
return getOtherFieldBindings(scope);
}
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+ if (runtimeTimeType == null || compileTimeType == null)
+ return;
+ // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
+ FieldBinding field = null;
+ int length = this.otherBindings == null ? 0 : this.otherBindings.length;
+ if (length == 0) {
+ if ((this.bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
+ field = (FieldBinding) this.binding;
+ }
+ } else {
+ field = this.otherBindings[length-1];
+ }
+ if (field != null) {
+ FieldBinding originalBinding = field.original();
+ if (originalBinding != field) {
+ // extra cast needed if method return type has type variable
+ if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+ setGenericCast(length,originalBinding.type.genericCast(scope.boxing(runtimeTimeType))); // runtimeType could be base type in boxing case
+ }
+ }
+ }
+ super.computeConversion(scope, runtimeTimeType, compileTimeType);
+ }
+
public void generateAssignment(
BlockScope currentScope,
CodeStream codeStream,
Assignment assignment,
boolean valueRequired) {
- generateReadSequence(currentScope, codeStream);
+ FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
assignment.expression.generateCode(currentScope, codeStream, true);
fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
// equivalent to valuesRequired[maxOtherBindings]
@@ -280,21 +313,21 @@ public class QualifiedNameReference extends NameReference {
codeStream.generateConstant(constant, implicitConversion);
}
} else {
- generateReadSequence(currentScope, codeStream);
+ FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
if (valueRequired) {
if (lastFieldBinding.declaringClass == null) { // array length
codeStream.arraylength();
codeStream.generateImplicitConversion(implicitConversion);
} else {
- if (lastFieldBinding.constant != NotAConstant) {
+ if (lastFieldBinding.isConstantValue()) {
if (!lastFieldBinding.isStatic()){
codeStream.invokeObjectGetClass();
codeStream.pop();
}
// inline the last field constant
- codeStream.generateConstant(lastFieldBinding.constant, implicitConversion);
+ codeStream.generateConstant(lastFieldBinding.constant(), implicitConversion);
} else {
- SyntheticAccessMethodBinding accessor =
+ SyntheticMethodBinding accessor =
syntheticReadAccessors == null
? null
: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -307,6 +340,8 @@ public class QualifiedNameReference extends NameReference {
} else {
codeStream.invokestatic(accessor);
}
+ TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
+ if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
codeStream.generateImplicitConversion(implicitConversion);
}
}
@@ -328,8 +363,8 @@ public class QualifiedNameReference extends NameReference {
int assignmentImplicitConversion,
boolean valueRequired) {
- generateReadSequence(currentScope, codeStream);
- SyntheticAccessMethodBinding accessor =
+ FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+ SyntheticMethodBinding accessor =
syntheticReadAccessors == null
? null
: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -350,21 +385,25 @@ public class QualifiedNameReference extends NameReference {
// the last field access is a write access
// perform the actual compound operation
int operationTypeID;
- if ((operationTypeID = implicitConversion >> 4) == T_String) {
- codeStream.generateStringAppend(currentScope, null, expression);
- } else {
- // promote the array reference to the suitable operation type
- codeStream.generateImplicitConversion(implicitConversion);
- // generate the increment value (will by itself be promoted to the operation value)
- if (expression == IntLiteral.One) { // prefix operation
- codeStream.generateConstant(expression.constant, implicitConversion);
- } else {
- expression.generateCode(currentScope, codeStream, true);
- }
- // perform the operation
- codeStream.sendOperator(operator, operationTypeID);
- // cast the value back to the array reference type
- codeStream.generateImplicitConversion(assignmentImplicitConversion);
+ switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+ case T_JavaLangString :
+ case T_JavaLangObject :
+ case T_undefined :
+ codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+ break;
+ default :
+ // promote the array reference to the suitable operation type
+ codeStream.generateImplicitConversion(implicitConversion);
+ // generate the increment value (will by itself be promoted to the operation value)
+ if (expression == IntLiteral.One) { // prefix operation
+ codeStream.generateConstant(expression.constant, implicitConversion);
+ } else {
+ expression.generateCode(currentScope, codeStream, true);
+ }
+ // perform the operation
+ codeStream.sendOperator(operator, operationTypeID);
+ // cast the value back to the array reference type
+ codeStream.generateImplicitConversion(assignmentImplicitConversion);
}
// actual assignment
fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
@@ -375,8 +414,9 @@ public class QualifiedNameReference extends NameReference {
CodeStream codeStream,
CompoundAssignment postIncrement,
boolean valueRequired) {
- generateReadSequence(currentScope, codeStream);
- SyntheticAccessMethodBinding accessor =
+
+ FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
+ SyntheticMethodBinding accessor =
syntheticReadAccessors == null
? null
: syntheticReadAccessors[syntheticReadAccessors.length - 1];
@@ -412,10 +452,11 @@ public class QualifiedNameReference extends NameReference {
}
}
}
+ codeStream.generateImplicitConversion(implicitConversion);
codeStream.generateConstant(
postIncrement.expression.constant,
implicitConversion);
- codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
+ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
codeStream.generateImplicitConversion(
postIncrement.assignmentImplicitConversion);
fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, false);
@@ -424,19 +465,20 @@ public class QualifiedNameReference extends NameReference {
* Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
* for a read or write access.
*/
- public void generateReadSequence(
- BlockScope currentScope,
- CodeStream codeStream) {
+ public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
// determine the rank until which we now we do not need any actual value for the field access
int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length;
-
boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
+ FieldBinding lastFieldBinding = null;
+ TypeBinding lastGenericCast = null;
+
switch (bits & RestrictiveFlagMASK) {
- case FIELD :
+ case Binding.FIELD :
lastFieldBinding = (FieldBinding) this.codegenBinding;
+ lastGenericCast = this.genericCast;
// if first field is actually constant, we can inline it
- if (lastFieldBinding.constant != NotAConstant) {
+ if (lastFieldBinding.isConstantValue()) {
break;
}
if (needValue && !lastFieldBinding.isStatic()) {
@@ -449,13 +491,12 @@ public class QualifiedNameReference extends NameReference {
}
}
break;
- case LOCAL : // reading the first local variable
- lastFieldBinding = null;
+ case Binding.LOCAL : // reading the first local variable
if (!needValue) break; // no value needed
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
// regular local variable read
- if (localBinding.constant != NotAConstant) {
- codeStream.generateConstant(localBinding.constant, 0);
+ if (localBinding.isConstantValue()) {
+ codeStream.generateConstant(localBinding.constant(), 0);
// no implicit conversion
} else {
// outer local?
@@ -468,24 +509,25 @@ public class QualifiedNameReference extends NameReference {
}
}
}
-
+
// all intermediate field accesses are read accesses
// only the last field binding is a write access
if (this.otherCodegenBindings != null) {
for (int i = 0; i < otherBindingsCount; i++) {
FieldBinding nextField = this.otherCodegenBindings[i];
+ TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
if (lastFieldBinding != null) {
needValue = !nextField.isStatic();
if (needValue) {
MethodBinding accessor =
syntheticReadAccessors == null ? null : syntheticReadAccessors[i];
if (accessor == null) {
- if (lastFieldBinding.constant != NotAConstant) {
- if (this.lastFieldBinding != this.codegenBinding && !this.lastFieldBinding.isStatic()) {
+ if (lastFieldBinding.isConstantValue()) {
+ if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
codeStream.invokeObjectGetClass(); // perform null check
codeStream.pop();
}
- codeStream.generateConstant(lastFieldBinding.constant, 0);
+ codeStream.generateConstant(lastFieldBinding.constant(), 0);
} else if (lastFieldBinding.isStatic()) {
codeStream.getstatic(lastFieldBinding);
} else {
@@ -494,42 +536,75 @@ public class QualifiedNameReference extends NameReference {
} else {
codeStream.invokestatic(accessor);
}
+ if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
} else {
- if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){
+ if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
codeStream.invokeObjectGetClass(); // perform null check
codeStream.pop();
}
}
}
- this.lastFieldBinding = nextField;
+ lastFieldBinding = nextField;
+ lastGenericCast = nextGenericCast;
}
}
+ return lastFieldBinding;
}
public void generateReceiver(CodeStream codeStream) {
codeStream.aload_0();
}
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return null;
+ }
+
+ // get the matching codegenBinding
+ protected FieldBinding getCodegenBinding(int index) {
+ if (index == 0){
+ return (FieldBinding)this.codegenBinding;
+ } else {
+ return this.otherCodegenBindings[index-1];
+ }
+ }
+
+ // get the matching generic cast
+ protected TypeBinding getGenericCast(int index) {
+ if (index == 0){
+ return this.genericCast;
+ } else {
+ if (this.otherGenericCasts == null) return null;
+ return this.otherGenericCasts[index-1];
+ }
+ }
+
public TypeBinding getOtherFieldBindings(BlockScope scope) {
// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
int length = tokens.length;
- if ((bits & FIELD) != 0) {
- FieldBinding fieldBinding = (FieldBinding) binding;
- if (!fieldBinding.isStatic()) {
+ FieldBinding field;
+ if ((bits & Binding.FIELD) != 0) {
+ field = (FieldBinding) this.binding;
+ if (!field.isStatic()) {
//must check for the static status....
if (indexOfFirstFieldBinding > 1 //accessing to a field using a type as "receiver" is allowed only with static field
|| scope.methodScope().isStatic) { // the field is the first token of the qualified reference....
- scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
+ scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field);
return null;
}
} else {
// indirect static reference ?
if (indexOfFirstFieldBinding > 1
- && fieldBinding.declaringClass != actualReceiverType) {
- scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
+ && field.declaringClass != actualReceiverType) {
+ scope.problemReporter().indirectAccessToStaticField(this, field);
}
}
// only last field is actually a write access if any
- if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
- scope.problemReporter().deprecatedField(fieldBinding, this);
+ if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
+ scope.problemReporter().deprecatedField(field, this);
+ } else {
+ field = null;
}
TypeBinding type = ((VariableBinding) binding).type;
int index = indexOfFirstFieldBinding;
@@ -543,10 +618,9 @@ public class QualifiedNameReference extends NameReference {
otherDepths = new int[otherBindingsLength];
// fill the first constant (the one of the binding)
- this.constant =
- ((bits & FIELD) != 0)
+ this.constant = field != null
? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope)
- : ((VariableBinding) binding).constant;
+ : ((VariableBinding) binding).constant();
// save first depth, since will be updated by visibility checks of other bindings
int firstDepth = (bits & DepthMASK) >> DepthSHIFT;
// iteration on each field
@@ -555,8 +629,18 @@ public class QualifiedNameReference extends NameReference {
if (type == null)
return null; // could not resolve type prior to this point
+ // set generic cast of for previous field (if any)
+ if (field != null) {
+ FieldBinding originalBinding = field.original();
+ if (originalBinding != field) {
+ // extra cast needed if method return type has type variable
+ if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && type.id != T_JavaLangObject) {
+ setGenericCast(index-1,originalBinding.type.genericCast(type)); // type cannot be base-type even in boxing case
+ }
+ }
+ }
bits &= ~DepthMASK; // flush previous depth if any
- FieldBinding field = scope.getField(type, token, this);
+ field = scope.getField(type, token, this);
int place = index - indexOfFirstFieldBinding;
otherBindings[place] = field;
otherDepths[place] = (bits & DepthMASK) >> DepthSHIFT;
@@ -597,97 +681,50 @@ public class QualifiedNameReference extends NameReference {
if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) {
return;
}
- if ((bits & RestrictiveFlagMASK) == LOCAL) {
+ if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
currentScope.emulateOuterAccess((LocalVariableBinding) binding);
}
}
- public void manageSyntheticReadAccessIfNecessary(
+ /**
+ * index is <0 to denote write access emulation
+ */
+ public void manageSyntheticAccessIfNecessary(
BlockScope currentScope,
FieldBinding fieldBinding,
TypeBinding lastReceiverType,
int index,
FlowInfo flowInfo) {
+
if (!flowInfo.isReachable()) return;
- // index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings'
- if (fieldBinding.constant != NotAConstant)
+ // index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
+ if (fieldBinding.isConstantValue())
return;
- if (fieldBinding.isPrivate()) { // private access
- if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
- if (syntheticReadAccessors == null) {
- if (otherBindings == null)
- syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
- else
- syntheticReadAccessors =
- new SyntheticAccessMethodBinding[otherBindings.length + 1];
- }
- syntheticReadAccessors[index] = ((SourceTypeBinding) fieldBinding.declaringClass).addSyntheticMethod(fieldBinding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
- return;
- }
- } else if (fieldBinding.isProtected()){
- int depth = index == 0 ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[index-1];
- // implicit protected access (only for first one)
- if (depth > 0 && (fieldBinding.declaringClass.getPackage()
- != currentScope.enclosingSourceType().getPackage())) {
- if (syntheticReadAccessors == null) {
- if (otherBindings == null)
- syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
- else
- syntheticReadAccessors =
- new SyntheticAccessMethodBinding[otherBindings.length + 1];
- }
- syntheticReadAccessors[index] =
- ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
- .addSyntheticMethod(fieldBinding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
- return;
- }
- }
- // if the binding declaring class is not visible, need special action
- // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
- // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
- if (fieldBinding.declaringClass != lastReceiverType
- && !lastReceiverType.isArrayType()
- && fieldBinding.declaringClass != null
- && fieldBinding.constant == NotAConstant
- && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
- && (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
- && fieldBinding.declaringClass.id != T_Object)
- || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
- if (index == 0){
- this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
- } else {
- if (this.otherCodegenBindings == this.otherBindings){
- int l = this.otherBindings.length;
- System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
- }
- this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
- }
+
+ // if field from parameterized type got found, use the original field at codegen time
+ FieldBinding originalField = fieldBinding.original();
+ if (originalField != fieldBinding) {
+ setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField);
}
- }
- /*
- * No need to emulate access to protected fields since not implicitly accessed
- */
- public void manageSyntheticWriteAccessIfNecessary(
- BlockScope currentScope,
- FieldBinding fieldBinding,
- TypeBinding lastReceiverType,
- FlowInfo flowInfo) {
- if (!flowInfo.isReachable()) return;
- if (fieldBinding.isPrivate()) {
- if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
- syntheticWriteAccessor = ((SourceTypeBinding) fieldBinding.declaringClass)
- .addSyntheticMethod(fieldBinding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+
+ if (fieldBinding.isPrivate()) { // private access
+ FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
+ if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
+ setSyntheticAccessor(fieldBinding, index,
+ ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
+ currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
return;
}
} else if (fieldBinding.isProtected()){
- int depth = fieldBinding == binding ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[otherDepths.length-1];
- if (depth > 0 && (fieldBinding.declaringClass.getPackage()
- != currentScope.enclosingSourceType().getPackage())) {
- syntheticWriteAccessor = ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
- .addSyntheticMethod(fieldBinding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+ int depth = fieldBinding == binding
+ ? (bits & DepthMASK) >> DepthSHIFT
+ : otherDepths[index < 0 ? otherDepths.length-1 : index-1];
+
+ // implicit protected access
+ if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
+ FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
+ setSyntheticAccessor(fieldBinding, index,
+ ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
+ currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
return;
}
}
@@ -697,24 +734,19 @@ public class QualifiedNameReference extends NameReference {
if (fieldBinding.declaringClass != lastReceiverType
&& !lastReceiverType.isArrayType()
&& fieldBinding.declaringClass != null
- && fieldBinding.constant == NotAConstant
+ && !fieldBinding.isConstantValue()
&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
&& (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
- && fieldBinding.declaringClass.id != T_Object)
+ && fieldBinding.declaringClass.id != T_JavaLangObject)
|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
- if (fieldBinding == binding){
- this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
- } else {
- if (this.otherCodegenBindings == this.otherBindings){
- int l = this.otherBindings.length;
- System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
- }
- this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
- }
+ setCodegenBinding(
+ index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index,
+ currentScope.enclosingSourceType().getUpdatedFieldBinding(
+ getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index),
+ (ReferenceBinding)lastReceiverType.erasure()));
}
-
}
-
+
public StringBuffer printExpression(int indent, StringBuffer output) {
for (int i = 0; i < tokens.length; i++) {
@@ -741,19 +773,19 @@ public class QualifiedNameReference extends NameReference {
// field and/or local are done before type lookups
// the only available value for the restrictiveFlag BEFORE
// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
- this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
+ this.actualReceiverType = scope.enclosingSourceType();
constant = Constant.NotAConstant;
if ((this.codegenBinding = this.binding = scope.getBinding(tokens, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
switch (bits & RestrictiveFlagMASK) {
- case VARIABLE : //============only variable===========
- case TYPE | VARIABLE :
+ case Binding.VARIABLE : //============only variable===========
+ case Binding.TYPE | Binding.VARIABLE :
if (binding instanceof LocalVariableBinding) {
if (!((LocalVariableBinding) binding).isFinal() && ((bits & DepthMASK) != 0))
scope.problemReporter().cannotReferToNonFinalOuterLocal(
(LocalVariableBinding) binding,
this);
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= LOCAL;
+ bits |= Binding.LOCAL;
return this.resolvedType = getOtherFieldBindings(scope);
}
if (binding instanceof FieldBinding) {
@@ -774,7 +806,7 @@ public class QualifiedNameReference extends NameReference {
scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
}
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= FIELD;
+ bits |= Binding.FIELD;
// check for deprecated receiver type
// deprecation check for receiver type if not first token
@@ -787,16 +819,56 @@ public class QualifiedNameReference extends NameReference {
}
// thus it was a type
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= TYPE;
- case TYPE : //=============only type ==============
- if (isTypeUseDeprecated((TypeBinding) binding, scope))
- scope.problemReporter().deprecatedType((TypeBinding) binding, this);
- return this.resolvedType = (TypeBinding) binding;
+ bits |= Binding.TYPE;
+ case Binding.TYPE : //=============only type ==============
+ TypeBinding type = (TypeBinding) binding;
+ if (isTypeUseDeprecated(type, scope))
+ scope.problemReporter().deprecatedType(type, this);
+ return this.resolvedType = scope.convertToRawType(type);
}
}
//========error cases===============
return this.resolvedType = this.reportError(scope);
}
+
+ // set the matching codegenBinding and generic cast
+ protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) {
+
+ if (index == 0){
+ this.codegenBinding = someCodegenBinding;
+ } else {
+ int length = this.otherBindings.length;
+ if (this.otherCodegenBindings == this.otherBindings){
+ System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length);
+ }
+ this.otherCodegenBindings[index-1] = someCodegenBinding;
+ }
+ }
+
+ // set the matching codegenBinding and generic cast
+ protected void setGenericCast(int index, TypeBinding someGenericCast) {
+
+ if (index == 0){
+ this.genericCast = someGenericCast;
+ } else {
+ if (this.otherGenericCasts == null) {
+ this.otherGenericCasts = new TypeBinding[this.otherBindings.length];
+ }
+ this.otherGenericCasts[index-1] = someGenericCast;
+ }
+ }
+
+ // set the matching synthetic accessor
+ protected void setSyntheticAccessor(FieldBinding fieldBinding, int index, SyntheticMethodBinding syntheticAccessor) {
+ if (index < 0) { // write-access ?
+ syntheticWriteAccessor = syntheticAccessor;
+ } else {
+ if (syntheticReadAccessors == null) {
+ syntheticReadAccessors = new SyntheticMethodBinding[otherBindings == null ? 1 : otherBindings.length + 1];
+ }
+ syntheticReadAccessors[index] = syntheticAccessor;
+ }
+ }
public void setFieldIndex(int index) {
this.indexOfFirstFieldBinding = index;
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
index 592c433..67e95fc 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
@@ -44,7 +44,7 @@ public class QualifiedSuperReference extends QualifiedThisReference {
if (currentCompatibleType == null)
return null; // error case
- if (currentCompatibleType.id == T_Object) {
+ if (currentCompatibleType.id == T_JavaLangObject) {
scope.problemReporter().cannotUseSuperInJavaLangObject(this);
return null;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
index 93e4c1c..9dcbb4c 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
@@ -72,15 +72,19 @@ public class QualifiedThisReference extends ThisReference {
public TypeBinding resolveType(BlockScope scope) {
constant = NotAConstant;
- this.resolvedType = this.qualification.resolveType(scope);
- if (this.resolvedType == null) return null;
-
+ TypeBinding type = this.resolvedType = this.qualification.resolveType(scope, true /* check bounds*/);
+ if (type == null) return null;
+ // X.this is not a raw type as denoting enclosing instance
+ if (type.isRawType()) {
+ RawTypeBinding rawType = (RawTypeBinding) type;
+ type = this.resolvedType = rawType.type; // unwrap
+ }
// the qualification MUST exactly match some enclosing type name
// Its possible to qualify 'this' by the name of the current class
int depth = 0;
this.currentCompatibleType = scope.referenceType().binding;
while (this.currentCompatibleType != null
- && this.currentCompatibleType != this.resolvedType) {
+ && this.currentCompatibleType != type) {
depth++;
this.currentCompatibleType = this.currentCompatibleType.isStatic() ? null : this.currentCompatibleType.enclosingType();
}
@@ -88,15 +92,15 @@ public class QualifiedThisReference extends ThisReference {
bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
if (this.currentCompatibleType == null) {
- scope.problemReporter().noSuchEnclosingInstance(this.resolvedType, this, false);
- return this.resolvedType;
+ scope.problemReporter().noSuchEnclosingInstance(type, this, false);
+ return type;
}
// Ensure one cannot write code like: B() { super(B.this); }
if (depth == 0) {
checkAccess(scope.methodScope());
} // if depth>0, path emulation will diagnose bad scenarii
- return this.resolvedType;
+ return type;
}
public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index b37276b..d3518a0 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -12,6 +12,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
public class QualifiedTypeReference extends TypeReference {
@@ -25,24 +26,65 @@ public class QualifiedTypeReference extends TypeReference {
sourceStart = (int) (sourcePositions[0]>>>32) ;
sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
}
-
- public QualifiedTypeReference(char[][] sources , TypeBinding type , long[] poss) {
- this(sources,poss);
- this.resolvedType = type;
- }
-
public TypeReference copyDims(int dim){
//return a type reference copy of me with some dimensions
//warning : the new type ref has a null binding
- return new ArrayQualifiedTypeReference(tokens,null,dim,sourcePositions) ;
+ return new ArrayQualifiedTypeReference(tokens, dim, sourcePositions);
}
-
- public TypeBinding getTypeBinding(Scope scope) {
+
+ protected TypeBinding findNextTypeBinding(int tokenIndex, Scope scope, PackageBinding packageBinding) {
+ try {
+ if (this.resolvedType == null) {
+ this.resolvedType = scope.getType(this.tokens[tokenIndex], packageBinding);
+ } else {
+ this.resolvedType = scope.getMemberType(this.tokens[tokenIndex], (ReferenceBinding) this.resolvedType);
+ if (this.resolvedType instanceof ProblemReferenceBinding) {
+ ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) this.resolvedType;
+ this.resolvedType = new ProblemReferenceBinding(
+ org.eclipse.jdt.core.compiler.CharOperation.subarray(this.tokens, 0, tokenIndex + 1),
+ problemBinding.original,
+ this.resolvedType.problemId());
+ }
+ }
+ return this.resolvedType;
+ } catch (AbortCompilation e) {
+ e.updateContext(this, scope.referenceCompilationUnit().compilationResult);
+ throw e;
+ }
+ }
+
+ protected TypeBinding getTypeBinding(Scope scope) {
if (this.resolvedType != null)
return this.resolvedType;
- return scope.getType(tokens);
+
+ Binding binding = scope.getPackage(this.tokens);
+ if (binding != null && !binding.isValidBinding())
+ return (ReferenceBinding) binding; // not found
+
+ PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
+ boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
+ ReferenceBinding qualifiedType = null;
+ for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) {
+ findNextTypeBinding(i, scope, packageBinding);
+ if (!this.resolvedType.isValidBinding())
+ return this.resolvedType;
+
+ if (isClassScope)
+ if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this, null)) // must connect hierarchy to find inherited member types
+ return null;
+ ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
+ if (currentType.isGenericType()) {
+ qualifiedType = scope.environment().createRawType(currentType, qualifiedType);
+ } else {
+ qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+ ? scope.createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType)
+ : currentType;
+ }
+ }
+ this.resolvedType = qualifiedType;
+ return this.resolvedType;
}
public char[][] getTypeName(){
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Reference.java b/src/org/eclipse/jdt/internal/compiler/ast/Reference.java
index 41d498b..5a62bb6 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -67,4 +67,19 @@ public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStr
public abstract void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired);
+public int nullStatus(FlowInfo flowInfo) {
+
+ if (this.constant != null && this.constant != NotAConstant)
+ return FlowInfo.NON_NULL; // constant expression cannot be null
+
+ LocalVariableBinding local = localVariableBinding();
+ if (local != null) {
+ if (flowInfo.isDefinitelyNull(local))
+ return FlowInfo.NULL;
+ if (flowInfo.isDefinitelyNonNull(local))
+ return FlowInfo.NON_NULL;
+ }
+ return FlowInfo.UNKNOWN;
+}
+
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index ca74dae..74b3192 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -18,7 +18,6 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
public class ReturnStatement extends Statement {
public Expression expression;
- public TypeBinding expressionType;
public boolean isSynchronized;
public SubRoutineStatement[] subroutines;
public boolean isAnySubRoutineEscaping = false;
@@ -92,7 +91,7 @@ public class ReturnStatement extends Statement {
}
} else {
this.saveValueVariable = null;
- if ((!isSynchronized) && (expressionType == BooleanBinding)) {
+ if (!isSynchronized && this.expression != null && this.expression.resolvedType == BooleanBinding) {
this.expression.bits |= ValueForReturnMASK;
}
}
@@ -151,7 +150,13 @@ public class ReturnStatement extends Statement {
if (expression == null) {
codeStream.return_();
} else {
- switch (expression.implicitConversion >> 4) {
+ final int implicitConversion = expression.implicitConversion;
+ if ((implicitConversion & BOXING) != 0) {
+ codeStream.areturn();
+ return;
+ }
+ int runtimeType = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+ switch (runtimeType) {
case T_boolean :
case T_int :
codeStream.ireturn();
@@ -187,7 +192,9 @@ public class ReturnStatement extends Statement {
expression.printExpression(0, output) ;
return output.append(';');
}
+
public void resolve(BlockScope scope) {
+
MethodScope methodScope = scope.methodScope();
MethodBinding methodBinding;
TypeBinding methodType =
@@ -196,6 +203,7 @@ public class ReturnStatement extends Statement {
? null
: methodBinding.returnType)
: VoidBinding;
+ TypeBinding expressionType;
if (methodType == VoidBinding) {
// the expression should be null
if (expression == null)
@@ -208,25 +216,30 @@ public class ReturnStatement extends Statement {
if (methodType != null) scope.problemReporter().shouldReturn(methodType, this);
return;
}
- if ((expressionType = expression.resolveType(scope)) == null)
- return;
-
- if (methodType != null && expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)) {
- // dealing with constant
- expression.implicitWidening(methodType, expressionType);
- return;
- }
+ expression.setExpectedType(methodType); // needed in case of generic method invocation
+ if ((expressionType = expression.resolveType(scope)) == null) return;
if (expressionType == VoidBinding) {
scope.problemReporter().attemptToReturnVoidValue(this);
return;
}
- if (methodType != null && expressionType.isCompatibleWith(methodType)) {
- expression.implicitWidening(methodType, expressionType);
+ if (methodType == null)
+ return;
+
+ if (methodType != expressionType) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(methodType, expressionType);
+ if (expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)
+ || expressionType.isCompatibleWith(methodType)) {
+
+ expression.computeConversion(scope, methodType, expressionType);
+ if (expressionType.needsUncheckedConversion(methodType)) {
+ scope.problemReporter().unsafeRawConversion(this.expression, expressionType, methodType);
+ }
+ return;
+ } else if (scope.isBoxingCompatibleWith(expressionType, methodType)) {
+ expression.computeConversion(scope, methodType, expressionType);
return;
}
- if (methodType != null){
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
- }
+ scope.problemReporter().typeMismatchError(expressionType, methodType, expression);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java b/src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java
new file mode 100644
index 0000000..ff9881f
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SingleMemberAnnotation.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+
+/**
+ * SingleMemberAnnotation node
+ */
+public class SingleMemberAnnotation extends Annotation {
+
+ public Expression memberValue;
+ public MemberValuePair singlePair; // fake pair, only value has accurate positions
+
+ public SingleMemberAnnotation(TypeReference type, int sourceStart) {
+ this.type = type;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = type.sourceEnd;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Annotation#memberValuePairs()
+ */
+ public MemberValuePair[] memberValuePairs() {
+ this.singlePair = new MemberValuePair(VALUE, this.memberValue.sourceStart, this.memberValue.sourceEnd, this.memberValue);
+ return new MemberValuePair[] { singlePair };
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output) {
+ super.printExpression(indent, output);
+ output.append('(');
+ this.memberValue.printExpression(indent, output);
+ return output.append(')');
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.memberValue != null) {
+ this.memberValue.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+ public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.memberValue != null) {
+ this.memberValue.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/src/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 908732b..eb937a6 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -19,11 +19,12 @@ import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
public class SingleNameReference extends NameReference implements OperatorIds {
+
public char[] token;
-
public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
public static final int READ = 0;
public static final int WRITE = 1;
+ public TypeBinding genericCast;
public SingleNameReference(char[] source, long pos) {
super();
@@ -37,7 +38,7 @@ public class SingleNameReference extends NameReference implements OperatorIds {
// compound assignment extra work
if (isCompound) { // check the variable part is initialized if blank final
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // reading a field
+ case Binding.FIELD : // reading a field
FieldBinding fieldBinding;
if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
@@ -45,9 +46,9 @@ public class SingleNameReference extends NameReference implements OperatorIds {
currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
}
}
- manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
break;
- case LOCAL : // reading a local variable
+ case Binding.LOCAL : // reading a local variable
// check if assigning a final blank field
LocalVariableBinding localBinding;
if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
@@ -65,8 +66,8 @@ public class SingleNameReference extends NameReference implements OperatorIds {
flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
}
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // assigning to a field
- manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+ case Binding.FIELD : // assigning to a field
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
// check if assigning a final field
FieldBinding fieldBinding;
@@ -84,7 +85,7 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
}
break;
- case LOCAL : // assigning to a local variable
+ case Binding.LOCAL : // assigning to a local variable
LocalVariableBinding localBinding = (LocalVariableBinding) binding;
if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
bits |= FirstAssignmentToLocalMASK;
@@ -116,9 +117,9 @@ public class SingleNameReference extends NameReference implements OperatorIds {
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // reading a field
+ case Binding.FIELD : // reading a field
if (valueRequired) {
- manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+ manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
}
// check if reading a final blank field
FieldBinding fieldBinding;
@@ -129,7 +130,7 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
}
break;
- case LOCAL : // reading a local variable
+ case Binding.LOCAL : // reading a local variable
LocalVariableBinding localBinding;
if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
@@ -145,12 +146,13 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
return flowInfo;
}
+
public TypeBinding checkFieldAccess(BlockScope scope) {
FieldBinding fieldBinding = (FieldBinding) binding;
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= FIELD;
+ bits |= Binding.FIELD;
if (!((FieldBinding) binding).isStatic()) {
// must check for the static status....
if (scope.methodScope().isStatic) {
@@ -178,6 +180,26 @@ public class SingleNameReference extends NameReference implements OperatorIds {
return fieldBinding.type;
}
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+ if (runtimeTimeType == null || compileTimeType == null)
+ return;
+ if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
+ // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
+ FieldBinding originalBinding = ((FieldBinding)this.binding).original();
+ if (originalBinding != this.binding) {
+ // extra cast needed if method return type has type variable
+ if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+ this.genericCast = originalBinding.type.genericCast(scope.boxing(runtimeTimeType)); // runtimeType could be base type in boxing case
+ }
+ }
+ }
+ super.computeConversion(scope, runtimeTimeType, compileTimeType);
+ }
+
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
// optimizing assignment like: i = i + 1 or i = 1 + i
@@ -194,15 +216,15 @@ public class SingleNameReference extends NameReference implements OperatorIds {
&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
- && ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
- && ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+ && (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
+ && (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
return;
}
}
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // assigning to a field
+ case Binding.FIELD : // assigning to a field
FieldBinding fieldBinding;
if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
if ((bits & DepthMASK) != 0) {
@@ -218,8 +240,9 @@ public class SingleNameReference extends NameReference implements OperatorIds {
if (valueRequired) {
codeStream.generateImplicitConversion(assignment.implicitConversion);
}
+ // no need for generic cast as value got dupped
return;
- case LOCAL : // assigning to a local variable
+ case Binding.LOCAL : // assigning to a local variable
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
if (localBinding.resolvedPosition != -1) {
assignment.expression.generateCode(currentScope, codeStream, true);
@@ -272,10 +295,10 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
} else {
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // reading a field
+ case Binding.FIELD : // reading a field
FieldBinding fieldBinding;
if (valueRequired) {
- if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
+ if (!(fieldBinding = (FieldBinding) this.codegenBinding).isConstantValue()) { // directly use inlined value for constant fields
boolean isStatic;
if (!(isStatic = fieldBinding.isStatic())) {
if ((bits & DepthMASK) != 0) {
@@ -296,13 +319,14 @@ public class SingleNameReference extends NameReference implements OperatorIds {
} else {
codeStream.invokestatic(syntheticAccessors[READ]);
}
+ if (this.genericCast != null) codeStream.checkcast(this.genericCast);
codeStream.generateImplicitConversion(implicitConversion);
- } else { // directly use the inlined value
- codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+ } else { // directly use the inlined value
+ codeStream.generateConstant(fieldBinding.constant(), implicitConversion);
}
}
break;
- case LOCAL : // reading a local
+ case Binding.LOCAL : // reading a local
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
if (valueRequired) {
// outer local?
@@ -343,7 +367,7 @@ public class SingleNameReference extends NameReference implements OperatorIds {
*/
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // assigning to a field
+ case Binding.FIELD : // assigning to a field
FieldBinding fieldBinding;
if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
@@ -367,14 +391,14 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
}
break;
- case LOCAL : // assigning to a local variable (cannot assign to outer local)
+ case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
Constant assignConstant;
int increment;
// using incr bytecode if possible
switch (localBinding.type.id) {
- case T_String :
- codeStream.generateStringAppend(currentScope, this, expression);
+ case T_JavaLangString :
+ codeStream.generateStringConcatenationAppend(currentScope, this, expression);
if (valueRequired) {
codeStream.dup();
}
@@ -406,31 +430,37 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
// perform the actual compound operation
int operationTypeID;
- if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
- // we enter here if the single name reference is a field of type java.lang.String or if the type of the
- // operation is java.lang.Object
- // For example: o = o + ""; // where the compiled type of o is java.lang.Object.
- codeStream.generateStringAppend(currentScope, null, expression);
- } else {
- // promote the array reference to the suitable operation type
- codeStream.generateImplicitConversion(implicitConversion);
- // generate the increment value (will by itself be promoted to the operation value)
- if (expression == IntLiteral.One){ // prefix operation
- codeStream.generateConstant(expression.constant, implicitConversion);
- } else {
- expression.generateCode(currentScope, codeStream, true);
- }
- // perform the operation
- codeStream.sendOperator(operator, operationTypeID);
- // cast the value back to the array reference type
- codeStream.generateImplicitConversion(assignmentImplicitConversion);
+ switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+ case T_JavaLangString :
+ case T_JavaLangObject :
+ case T_undefined :
+ // we enter here if the single name reference is a field of type java.lang.String or if the type of the
+ // operation is java.lang.Object
+ // For example: o = o + ""; // where the compiled type of o is java.lang.Object.
+ codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+ // no need for generic cast on previous #getfield since using Object string buffer methods.
+ break;
+ default :
+ // promote the array reference to the suitable operation type
+ codeStream.generateImplicitConversion(implicitConversion);
+ // generate the increment value (will by itself be promoted to the operation value)
+ if (expression == IntLiteral.One){ // prefix operation
+ codeStream.generateConstant(expression.constant, implicitConversion);
+ } else {
+ expression.generateCode(currentScope, codeStream, true);
+ }
+ // perform the operation
+ codeStream.sendOperator(operator, operationTypeID);
+ // cast the value back to the array reference type
+ codeStream.generateImplicitConversion(assignmentImplicitConversion);
}
// store the result back into the variable
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // assigning to a field
+ case Binding.FIELD : // assigning to a field
fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
+ // no need for generic cast as value got dupped
return;
- case LOCAL : // assigning to a local variable
+ case Binding.LOCAL : // assigning to a local variable
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
if (valueRequired) {
if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
@@ -445,7 +475,7 @@ public class SingleNameReference extends NameReference implements OperatorIds {
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
switch (bits & RestrictiveFlagMASK) {
- case FIELD : // assigning to a field
+ case Binding.FIELD : // assigning to a field
FieldBinding fieldBinding;
if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
@@ -483,12 +513,14 @@ public class SingleNameReference extends NameReference implements OperatorIds {
}
}
}
+ codeStream.generateImplicitConversion(implicitConversion);
codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
- codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
+ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+ // no need for generic cast
return;
- case LOCAL : // assigning to a local variable
+ case Binding.LOCAL : // assigning to a local variable
LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
// using incr bytecode if possible
if (localBinding.type == IntBinding) {
@@ -509,8 +541,9 @@ public class SingleNameReference extends NameReference implements OperatorIds {
codeStream.dup();
}
}
+ codeStream.generateImplicitConversion(implicitConversion);
codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
- codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
+ codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
codeStream.store(localBinding, false);
@@ -522,6 +555,13 @@ public class SingleNameReference extends NameReference implements OperatorIds {
codeStream.aload_0();
}
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+ public TypeBinding[] genericTypeArguments() {
+ return null;
+ }
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
@@ -529,11 +569,11 @@ public class SingleNameReference extends NameReference implements OperatorIds {
//If inlinable field, forget the access emulation, the code gen will directly target it
if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
- if ((bits & RestrictiveFlagMASK) == LOCAL) {
+ if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
currentScope.emulateOuterAccess((LocalVariableBinding) binding);
}
}
- public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
if (!flowInfo.isReachable()) return;
@@ -541,20 +581,20 @@ public class SingleNameReference extends NameReference implements OperatorIds {
if (constant != NotAConstant)
return;
- if ((bits & FIELD) != 0) {
+ if ((bits & Binding.FIELD) != 0) {
FieldBinding fieldBinding = (FieldBinding) binding;
+ FieldBinding codegenField = fieldBinding.original();
+ this.codegenBinding = codegenField;
if (((bits & DepthMASK) != 0)
- && (fieldBinding.isPrivate() // private access
- || (fieldBinding.isProtected() // implicit protected access
- && fieldBinding.declaringClass.getPackage()
- != currentScope.enclosingSourceType().getPackage()))) {
+ && (codegenField.isPrivate() // private access
+ || (codegenField.isProtected() // implicit protected access
+ && codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
if (syntheticAccessors == null)
syntheticAccessors = new MethodBinding[2];
- syntheticAccessors[READ] =
- ((SourceTypeBinding)currentScope.enclosingSourceType().
- enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
- addSyntheticMethod(fieldBinding, true);
- currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+ syntheticAccessors[isReadAccess ? READ : WRITE] =
+ ((SourceTypeBinding)currentScope.enclosingSourceType().
+ enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess);
+ currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
return;
}
// if the binding declaring class is not visible, need special action
@@ -564,47 +604,15 @@ public class SingleNameReference extends NameReference implements OperatorIds {
if (fieldBinding.declaringClass != this.actualReceiverType
&& !this.actualReceiverType.isArrayType()
&& fieldBinding.declaringClass != null
- && fieldBinding.constant == NotAConstant
+ && !fieldBinding.isConstantValue()
&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
&& !fieldBinding.isStatic()
- && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
- || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
- this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
- }
- }
- }
- public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
-
- if (!flowInfo.isReachable()) return;
- if ((bits & FIELD) != 0) {
- FieldBinding fieldBinding = (FieldBinding) binding;
- if (((bits & DepthMASK) != 0)
- && (fieldBinding.isPrivate() // private access
- || (fieldBinding.isProtected() // implicit protected access
- && fieldBinding.declaringClass.getPackage()
- != currentScope.enclosingSourceType().getPackage()))) {
- if (syntheticAccessors == null)
- syntheticAccessors = new MethodBinding[2];
- syntheticAccessors[WRITE] =
- ((SourceTypeBinding)currentScope.enclosingSourceType().
- enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
- addSyntheticMethod(fieldBinding, false);
- currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
- return;
- }
- // if the binding declaring class is not visible, need special action
- // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
- // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
- // and not from Object or implicit static field access.
- if (fieldBinding.declaringClass != this.actualReceiverType
- && !this.actualReceiverType.isArrayType()
- && fieldBinding.declaringClass != null
- && fieldBinding.constant == NotAConstant
- && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
- && !fieldBinding.isStatic()
- && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
- || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
- this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+ && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields (if there was any)
+ || !codegenField.declaringClass.canBeSeenBy(currentScope))){
+ this.codegenBinding =
+ currentScope.enclosingSourceType().getUpdatedFieldBinding(
+ codegenField,
+ (ReferenceBinding)this.actualReceiverType.erasure());
}
}
}
@@ -629,19 +637,24 @@ public class SingleNameReference extends NameReference implements OperatorIds {
public TypeBinding resolveType(BlockScope scope) {
// for code gen, harm the restrictiveFlag
- this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
-
- if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
+ if (this.actualReceiverType != null) {
+ this.binding = scope.getField(this.actualReceiverType, token, this);
+ } else {
+ this.actualReceiverType = scope.enclosingSourceType();
+ this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/);
+ }
+ this.codegenBinding = this.binding;
+ if (this.binding.isValidBinding()) {
switch (bits & RestrictiveFlagMASK) {
- case VARIABLE : // =========only variable============
- case VARIABLE | TYPE : //====both variable and type============
+ case Binding.VARIABLE : // =========only variable============
+ case Binding.VARIABLE | Binding.TYPE : //====both variable and type============
if (binding instanceof VariableBinding) {
VariableBinding variable = (VariableBinding) binding;
if (binding instanceof LocalVariableBinding) {
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= LOCAL;
+ bits |= Binding.LOCAL;
if ((this.bits & IsStrictlyAssignedMASK) == 0) {
- constant = variable.constant;
+ constant = variable.constant();
} else {
constant = NotAConstant;
}
@@ -660,13 +673,14 @@ public class SingleNameReference extends NameReference implements OperatorIds {
// thus it was a type
bits &= ~RestrictiveFlagMASK; // clear bits
- bits |= TYPE;
- case TYPE : //========only type==============
+ bits |= Binding.TYPE;
+ case Binding.TYPE : //========only type==============
constant = Constant.NotAConstant;
//deprecated test
- if (isTypeUseDeprecated((TypeBinding) binding, scope))
- scope.problemReporter().deprecatedType((TypeBinding) binding, this);
- return this.resolvedType = (TypeBinding) binding;
+ TypeBinding type = (TypeBinding)binding;
+ if (isTypeUseDeprecated(type, scope))
+ scope.problemReporter().deprecatedType(type, this);
+ return this.resolvedType = scope.convertToRawType(type);
}
}
@@ -684,4 +698,18 @@ public class SingleNameReference extends NameReference implements OperatorIds {
return new String(token);
}
+
+ /**
+ * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
+ * or thru a cast expression etc...
+ */
+ public LocalVariableBinding localVariableBinding() {
+ switch (bits & RestrictiveFlagMASK) {
+ case Binding.FIELD : // reading a field
+ break;
+ case Binding.LOCAL : // reading a local variable
+ return (LocalVariableBinding) this.binding;
+ }
+ return null;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index 4d29467..55655f0 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -25,22 +25,23 @@ public class SingleTypeReference extends TypeReference {
}
- public SingleTypeReference(char[] source ,TypeBinding type, long pos) {
- this(source, pos) ;
- this.resolvedType = type ;
- }
-
public TypeReference copyDims(int dim){
//return a type reference copy of me with some dimensions
//warning : the new type ref has a null binding
- return new ArrayTypeReference(token,null,dim,(((long)sourceStart)<<32)+sourceEnd) ;
+ return new ArrayTypeReference(token, dim,(((long)sourceStart)<<32)+sourceEnd);
}
- public TypeBinding getTypeBinding(Scope scope) {
+ protected TypeBinding getTypeBinding(Scope scope) {
if (this.resolvedType != null)
return this.resolvedType;
- return scope.getType(token);
+
+ this.resolvedType = scope.getType(token);
+
+ if (scope.kind == Scope.CLASS_SCOPE && this.resolvedType.isValidBinding())
+ if (((ClassScope) scope).detectHierarchyCycle(this.resolvedType, this, null))
+ return null;
+ return this.resolvedType;
}
public char [][] getTypeName() {
@@ -54,14 +55,15 @@ public class SingleTypeReference extends TypeReference {
public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
- ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
- if (!memberTb.isValidBinding()) {
- scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
+ ReferenceBinding memberType = scope.getMemberType(token, enclosingType);
+ if (!memberType.isValidBinding()) {
+ this.resolvedType = memberType;
+ scope.problemReporter().invalidEnclosingType(this, memberType, enclosingType);
return null;
}
- if (isTypeUseDeprecated(memberTb, scope))
- scope.problemReporter().deprecatedType(memberTb, this);
- return this.resolvedType = memberTb;
+ if (isTypeUseDeprecated(memberType, scope))
+ scope.problemReporter().deprecatedType(memberType, this);
+ return this.resolvedType = scope.convertToRawType(memberType);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Statement.java b/src/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 2e240f7..591165d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -10,9 +10,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
public abstract class Statement extends ASTNode {
@@ -40,7 +40,59 @@ public abstract class Statement extends ASTNode {
}
return false;
}
-
+
+ /**
+ * Generate invocation arguments, considering varargs methods
+ */
+ public void generateArguments(MethodBinding binding, Expression[] arguments, BlockScope currentScope, CodeStream codeStream) {
+
+ if (binding.isVarargs()) {
+ // 5 possibilities exist for a call to the vararg method foo(int i, int ... value) :
+ // foo(1), foo(1, null), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new int[] {1, 2})
+ TypeBinding[] params = binding.parameters;
+ int paramLength = params.length;
+ int varArgIndex = paramLength - 1;
+ for (int i = 0; i < varArgIndex; i++) {
+ arguments[i].generateCode(currentScope, codeStream, true);
+ }
+
+ ArrayBinding varArgsType = (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
+ int argLength = arguments == null ? 0 : arguments.length;
+
+ generateVarargsArgument: {
+ if (argLength >= paramLength) {
+ // right number of arguments - could be inexact - pass argument as is
+ TypeBinding lastType = arguments[varArgIndex].resolvedType;
+ if (lastType == NullBinding || varArgsType.dimensions() == lastType.dimensions()) {
+ // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
+ arguments[varArgIndex].generateCode(currentScope, codeStream, true);
+ break generateVarargsArgument;
+ }
+ // right number but not directly compatible or too many arguments - wrap extra into array
+ // called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
+ // need to gen elements into an array, then gen each remaining element into created array
+ codeStream.generateInlinedValue(argLength - varArgIndex);
+ codeStream.newArray(varArgsType); // create a mono-dimensional array
+ int elementsTypeID = varArgsType.elementsType().id;
+ for (int i = varArgIndex; i < argLength; i++) {
+ codeStream.dup();
+ codeStream.generateInlinedValue(i - varArgIndex);
+ arguments[i].generateCode(currentScope, codeStream, true);
+ codeStream.arrayAtPut(elementsTypeID, false);
+ }
+ } else { // not enough arguments - pass extra empty array
+ // scenario: foo(1) --> foo(1, new int[0])
+ // generate code for an empty array of parameterType
+ codeStream.generateInlinedValue(0);
+ codeStream.newArray(varArgsType); // create a mono-dimensional array
+ }
+ }
+ } else if (arguments != null) { // standard generation for method arguments
+ for (int i = 0, max = arguments.length; i < max; i++)
+ arguments[i].generateCode(currentScope, codeStream, true);
+ }
+ }
+
public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
public boolean isEmptyBlock() {
@@ -69,11 +121,14 @@ public abstract class Statement extends ASTNode {
public abstract void resolve(BlockScope scope);
+ /**
+ * Returns case constant associated to this statement (NotAConstant if none)
+ */
public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
// statement within a switch that are not case are treated as normal statement....
resolve(scope);
- return null;
+ return NotAConstant;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java b/src/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
index 77ee9cc..1ea7892 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
@@ -18,7 +18,7 @@ import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
*/
public class StringLiteralConcatenation extends StringLiteral {
private static final int INITIAL_SIZE = 5;
- public StringLiteral[] literals;
+ public Expression[] literals;
public int counter;
/**
* Build a two-strings literal
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
index 59b697b..754efdf 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
@@ -44,8 +44,10 @@ public abstract class SubRoutineStatement extends Statement {
if (currentLabel.start == currentLabel.codeStream.position) {
// discard empty exception handler
this.anyExceptionLabels[--this.anyExceptionLabelsCount] = null;
+ currentLabel.codeStream.removeExceptionHandler(currentLabel);
+ } else {
+ currentLabel.placeEnd();
}
- currentLabel.placeEnd();
}
public void placeAllAnyExceptionHandlers() {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SuperReference.java b/src/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
index a877d12..9519a34 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
@@ -54,7 +54,7 @@ public class SuperReference extends ThisReference {
if (!checkAccess(scope.methodScope()))
return null;
SourceTypeBinding enclosingTb = scope.enclosingSourceType();
- if (enclosingTb.id == T_Object) {
+ if (enclosingTb.id == T_JavaLangObject) {
scope.problemReporter().cannotUseSuperInJavaLangObject(this);
return null;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index 65cddb1..6050f9f 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -11,10 +11,10 @@
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class SwitchStatement extends Statement {
@@ -26,8 +26,9 @@ public class SwitchStatement extends Statement {
public Label breakLabel;
public CaseStatement[] cases;
public CaseStatement defaultCase;
- public int caseCount = 0;
public int blockStart;
+ public int caseCount;
+ int[] constants;
// for local variables table attributes
int preSwitchInitStateIndex = -1;
@@ -101,87 +102,79 @@ public class SwitchStatement extends Statement {
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
try {
- int[] sortedIndexes = new int[caseCount];
- int[] localKeysCopy;
if ((bits & IsReachableMASK) == 0) {
return;
}
int pc = codeStream.position;
// prepare the labels and constants
- breakLabel.initialize(codeStream);
- CaseLabel[] caseLabels = new CaseLabel[caseCount];
- int[] constants = new int[caseCount];
- boolean needSwitch = caseCount != 0;
+ this.breakLabel.initialize(codeStream);
+ CaseLabel[] caseLabels = new CaseLabel[this.caseCount];
+ boolean needSwitch = this.caseCount != 0;
for (int i = 0; i < caseCount; i++) {
- constants[i] = cases[i].constantExpression.constant.intValue();
cases[i].targetLabel = (caseLabels[i] = new CaseLabel(codeStream));
}
-
- // we sort the keys to be able to generate the code for tableswitch or lookupswitch
- for (int i = 0; i < caseCount; i++) {
- sortedIndexes[i] = i;
- }
- System.arraycopy(
- constants,
- 0,
- (localKeysCopy = new int[caseCount]),
- 0,
- caseCount);
- CodeStream.sort(localKeysCopy, 0, caseCount - 1, sortedIndexes);
CaseLabel defaultLabel = new CaseLabel(codeStream);
if (defaultCase != null) {
defaultCase.targetLabel = defaultLabel;
}
// generate expression testes
expression.generateCode(currentScope, codeStream, needSwitch);
-
// generate the appropriate switch table/lookup bytecode
if (needSwitch) {
- int max = localKeysCopy[caseCount - 1];
+ int[] sortedIndexes = new int[this.caseCount];
+ // we sort the keys to be able to generate the code for tableswitch or lookupswitch
+ for (int i = 0; i < caseCount; i++) {
+ sortedIndexes[i] = i;
+ }
+ int[] localKeysCopy;
+ System.arraycopy(this.constants, 0, (localKeysCopy = new int[this.caseCount]), 0, this.caseCount);
+ CodeStream.sort(localKeysCopy, 0, this.caseCount - 1, sortedIndexes);
+
+ // for enum constants, actually switch on constant ordinal()
+ if (this.expression.resolvedType.isEnum()) {
+ codeStream.invokeEnumOrdinal(this.expression.resolvedType.constantPoolName());
+ }
+ int max = localKeysCopy[this.caseCount - 1];
int min = localKeysCopy[0];
if ((long) (caseCount * 2.5) > ((long) max - (long) min)) {
// work-around 1.3 VM bug, if max>0x7FFF0000, must use lookup bytecode
// see http://dev.eclipse.org/bugs/show_bug.cgi?id=21557
if (max > 0x7FFF0000 && currentScope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
- codeStream.lookupswitch(defaultLabel, constants, sortedIndexes, caseLabels);
+ codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
} else {
codeStream.tableswitch(
defaultLabel,
min,
max,
- constants,
+ this.constants,
sortedIndexes,
caseLabels);
}
} else {
- codeStream.lookupswitch(defaultLabel, constants, sortedIndexes, caseLabels);
+ codeStream.lookupswitch(defaultLabel, this.constants, sortedIndexes, caseLabels);
}
codeStream.updateLastRecordedEndPC(codeStream.position);
}
// generate the switch block statements
int caseIndex = 0;
- if (statements != null) {
- for (int i = 0, maxCases = statements.length; i < maxCases; i++) {
- Statement statement = statements[i];
- if ((caseIndex < caseCount) && (statement == cases[caseIndex])) { // statements[i] is a case
- this.scope.switchCase = cases[caseIndex]; // record entering in a switch case block
+ if (this.statements != null) {
+ for (int i = 0, maxCases = this.statements.length; i < maxCases; i++) {
+ Statement statement = this.statements[i];
+ if ((caseIndex < this.caseCount) && (statement == this.cases[caseIndex])) { // statements[i] is a case
+ this.scope.switchCase = this.cases[caseIndex]; // record entering in a switch case block
if (preSwitchInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preSwitchInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
}
caseIndex++;
} else {
- if (statement == defaultCase) { // statements[i] is a case or a default case
- this.scope.switchCase = defaultCase; // record entering in a switch case block
+ if (statement == this.defaultCase) { // statements[i] is a case or a default case
+ this.scope.switchCase = this.defaultCase; // record entering in a switch case block
if (preSwitchInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preSwitchInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preSwitchInitStateIndex);
}
}
}
@@ -189,19 +182,17 @@ public class SwitchStatement extends Statement {
}
}
// place the trailing labels (for break and default case)
- breakLabel.place();
+ this.breakLabel.place();
if (defaultCase == null) {
defaultLabel.place();
}
// May loose some local variable initializations : affecting the local variable attributes
if (mergedInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- mergedInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
}
if (scope != currentScope) {
- codeStream.exitUserScope(scope);
+ codeStream.exitUserScope(this.scope);
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
} finally {
@@ -230,60 +221,71 @@ public class SwitchStatement extends Statement {
public void resolve(BlockScope upperScope) {
try {
- TypeBinding testType = expression.resolveType(upperScope);
- if (testType == null)
+ TypeBinding expressionType = expression.resolveType(upperScope);
+ if (expressionType == null)
return;
- expression.implicitWidening(testType, testType);
- if (!(expression.isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
- if (!testType.isCompatibleWith(IntBinding)) {
- upperScope.problemReporter().incorrectSwitchType(expression, testType);
- return;
+ expression.computeConversion(upperScope, expressionType, expressionType);
+ checkType: {
+ if (expressionType.isBaseType()) {
+ if (expression.isConstantValueOfTypeAssignableToType(expressionType, IntBinding))
+ break checkType;
+ if (expressionType.isCompatibleWith(IntBinding))
+ break checkType;
+ } else if (expressionType.isEnum()) {
+ break checkType;
+ } else if (upperScope.isBoxingCompatibleWith(expressionType, IntBinding)) {
+ expression.computeConversion(upperScope, IntBinding, expressionType);
+ break checkType;
}
+ upperScope.problemReporter().incorrectSwitchType(expression, expressionType);
+ // TODO (philippe) could keep analyzing switch statements in case of error
+ return;
}
if (statements != null) {
scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope);
int length;
// collection of cases is too big but we will only iterate until caseCount
cases = new CaseStatement[length = statements.length];
- int[] casesValues = new int[length];
+ this.constants = new int[length];
CaseStatement[] duplicateCaseStatements = null;
int duplicateCaseStatementsCounter = 0;
int counter = 0;
for (int i = 0; i < length; i++) {
Constant constant;
final Statement statement = statements[i];
- if ((constant = statement.resolveCase(scope, testType, this)) != null) {
+ if ((constant = statement.resolveCase(scope, expressionType, this)) != Constant.NotAConstant) {
+ int key = constant.intValue();
//----check for duplicate case statement------------
- if (constant != NotAConstant) {
- int key = constant.intValue();
- for (int j = 0; j < counter; j++) {
- if (casesValues[j] == key) {
- final CaseStatement currentCaseStatement = (CaseStatement) statement;
- if (duplicateCaseStatements == null) {
- scope.problemReporter().duplicateCase(cases[j]);
+ for (int j = 0; j < counter; j++) {
+ if (this.constants[j] == key) {
+ final CaseStatement currentCaseStatement = (CaseStatement) statement;
+ if (duplicateCaseStatements == null) {
+ scope.problemReporter().duplicateCase(cases[j]);
+ scope.problemReporter().duplicateCase(currentCaseStatement);
+ duplicateCaseStatements = new CaseStatement[length];
+ duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
+ duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
+ } else {
+ boolean found = false;
+ searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
+ if (duplicateCaseStatements[k] == statement) {
+ found = true;
+ break searchReportedDuplicate;
+ }
+ }
+ if (!found) {
scope.problemReporter().duplicateCase(currentCaseStatement);
- duplicateCaseStatements = new CaseStatement[length];
- duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
- } else {
- boolean found = false;
- searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
- if (duplicateCaseStatements[k] == statement) {
- found = true;
- break searchReportedDuplicate;
- }
- }
- if (!found) {
- scope.problemReporter().duplicateCase(currentCaseStatement);
- duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
- }
}
}
}
- casesValues[counter++] = key;
}
+ this.constants[counter++] = key;
}
}
+ if (length != counter) { // resize constants array
+ System.arraycopy(this.constants, 0, this.constants = new int[counter], 0, counter);
+ }
} else {
if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd);
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index 2a45c54..b49d6ad 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -41,6 +41,8 @@ public class SynchronizedStatement extends SubRoutineStatement {
FlowContext flowContext,
FlowInfo flowInfo) {
+ // TODO (philippe) shouldn't it be protected by a check whether reachable statement ?
+
// mark the synthetic variable as being used
synchroVariable.useFlag = LocalVariableBinding.USED;
@@ -69,7 +71,7 @@ public class SynchronizedStatement extends SubRoutineStatement {
* @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
+
if ((bits & IsReachableMASK) == 0) {
return;
}
@@ -80,7 +82,7 @@ public class SynchronizedStatement extends SubRoutineStatement {
this.anyExceptionLabelsCount = 0;
}
int pc = codeStream.position;
-
+
// generate the synchronization expression
expression.generateCode(scope, codeStream, true);
if (block.isEmptyBlock()) {
@@ -97,7 +99,7 @@ public class SynchronizedStatement extends SubRoutineStatement {
// enter the monitor
codeStream.store(synchroVariable, true);
codeStream.monitorenter();
-
+
// generate the body of the synchronized block
this.enterAnyExceptionHandler(codeStream);
block.generateCode(scope, codeStream);
@@ -105,14 +107,16 @@ public class SynchronizedStatement extends SubRoutineStatement {
if (!blockExit) {
codeStream.load(synchroVariable);
codeStream.monitorexit();
+ this.exitAnyExceptionHandler();
codeStream.goto_(endLabel);
+ this.enterAnyExceptionHandler(codeStream);
}
// generate the body of the exception handler
- this.exitAnyExceptionHandler();
this.placeAllAnyExceptionHandlers();
codeStream.incrStackSize(1);
codeStream.load(synchroVariable);
codeStream.monitorexit();
+ this.exitAnyExceptionHandler();
codeStream.athrow();
if (!blockExit) {
endLabel.place();
@@ -163,8 +167,8 @@ public class SynchronizedStatement extends SubRoutineStatement {
//continue even on errors in order to have the TC done into the statements
synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, AccDefault, false);
scope.addLocalVariable(synchroVariable);
- synchroVariable.constant = NotAConstant; // not inlinable
- expression.implicitWidening(type, type);
+ synchroVariable.setConstant(NotAConstant); // not inlinable
+ expression.computeConversion(scope, type, type);
block.resolveUsing(scope);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/src/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
index 78ccdfa..c81c876 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
@@ -97,6 +97,10 @@ public class ThisReference extends Reference {
return true ;
}
+ public int nullStatus(FlowInfo flowInfo) {
+ return FlowInfo.NON_NULL;
+ }
+
public StringBuffer printExpression(int indent, StringBuffer output){
if (this.isImplicitThis()) return output;
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
index dac8920..515d313 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
@@ -68,7 +68,7 @@ public class ThrowStatement extends Statement {
// if compliant with 1.4, this problem will not be reported
scope.problemReporter().cannotThrowNull(this);
}
- exception.implicitWidening(exceptionType, exceptionType);
+ exception.computeConversion(scope, exceptionType, exceptionType);
}
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java b/src/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
index 14dc78f..a3bd34d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
@@ -23,8 +23,8 @@ public TrueLiteral(int s , int e) {
super(s,e);
}
public void computeConstant() {
-
- constant = Constant.fromValue(true);}
+ this.constant = Constant.fromValue(true);
+}
/**
* Code generation for the true literal
*
@@ -34,8 +34,9 @@ public void computeConstant() {
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
- if (valueRequired)
- codeStream.iconst_1();
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index bda4130..9101bce 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -83,7 +83,7 @@ public class TryStatement extends SubRoutineStatement {
.analyseCode(
currentScope,
finallyContext = new FinallyFlowContext(flowContext, finallyBlock),
- flowInfo.copy())
+ flowInfo.copy().unconditionalInits().discardNullRelatedInitializations())
.unconditionalInits();
if (subInfo == FlowInfo.DEAD_END) {
isSubRoutineEscaping = true;
@@ -128,7 +128,10 @@ public class TryStatement extends SubRoutineStatement {
.addPotentialInitializationsFrom(handlingContext.initsOnReturn);
// catch var is always set
- catchInfo.markAsDefinitelyAssigned(catchArguments[i].binding);
+ LocalVariableBinding catchArg = catchArguments[i].binding;
+ FlowContext catchContext = insideSubContext == null ? flowContext : insideSubContext;
+ catchInfo.markAsDefinitelyAssigned(catchArg);
+ catchInfo.markAsDefinitelyNonNull(catchArg);
/*
"If we are about to consider an unchecked exception handler, potential inits may have occured inside
the try block that need to be detected , e.g.
@@ -136,15 +139,13 @@ public class TryStatement extends SubRoutineStatement {
"(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index])
ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]."
*/
- // TODO (philippe) should only tag as unreachable if the catchblock cannot be reached?
- //??? if (!handlingContext.initsOnException(caughtExceptionTypes[i]).isReachable()){
if (tryBlock.statements == null) {
catchInfo.setReachMode(FlowInfo.UNREACHABLE);
}
catchInfo =
catchBlocks[i].analyseCode(
currentScope,
- insideSubContext == null ? flowContext : insideSubContext,
+ catchContext,
catchInfo);
catchExits[i] = !catchInfo.isReachable();
tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits());
@@ -159,7 +160,7 @@ public class TryStatement extends SubRoutineStatement {
// we also need to check potential multiple assignments of final variables inside the finally block
// need to include potential inits from returns inside the try/catch parts - 1GK2AOF
- finallyContext.complainOnRedundantFinalAssignments(
+ finallyContext.complainOnDeferredChecks(
tryInfo.isReachable()
? (tryInfo.addPotentialInitializationsFrom(insideSubContext.initsOnReturn))
: insideSubContext.initsOnReturn,
@@ -187,7 +188,6 @@ public class TryStatement extends SubRoutineStatement {
* returnAddress is only allocated if jsr is allowed
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
if ((bits & IsReachableMASK) == 0) {
return;
}
@@ -260,15 +260,11 @@ public class TryStatement extends SubRoutineStatement {
thrown) into their own catch variables, the one specified in the source
that must denote the handled exception.
*/
- if (catchArguments == null) {
- this.exitAnyExceptionHandler();
- } else {
+ if (catchArguments != null) {
for (int i = 0; i < maxCatches; i++) {
// May loose some local variable initializations : affecting the local variable attributes
if (preTryInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preTryInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
}
exceptionLabels[i].place();
codeStream.incrStackSize(1);
@@ -286,10 +282,6 @@ public class TryStatement extends SubRoutineStatement {
// Keep track of the pcs at diverging point for computing the local attribute
// since not passing the catchScope, the block generation will exitUserScope(catchScope)
catchBlocks[i].generateCode(scope, codeStream);
-
- if (i == maxCatches - 1) {
- this.exitAnyExceptionHandler();
- }
if (!catchExits[i]) {
switch(finallyMode) {
case FINALLY_SUBROUTINE :
@@ -306,55 +298,57 @@ public class TryStatement extends SubRoutineStatement {
}
}
}
+ this.exitAnyExceptionHandler();
// extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below)
ExceptionLabel naturalExitExceptionHandler =
- finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? this.enterAnyExceptionHandler(codeStream) : null;
-
+ finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? new ExceptionLabel(codeStream, null) : null;
+
// addition of a special handler so as to ensure that any uncaught exception (or exception thrown
// inside catch blocks) will run the finally block
int finallySequenceStartPC = codeStream.position;
if (subRoutineStartLabel != null) {
- // the additional handler is doing: jsr finallyBlock and rethrow TOS-exception
this.placeAllAnyExceptionHandlers();
-
+ if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();
+
if (preTryInitStateIndex != -1) {
// reset initialization state, as for a normal catch block
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preTryInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
}
codeStream.incrStackSize(1);
switch(finallyMode) {
-
case FINALLY_SUBROUTINE :
codeStream.store(anyExceptionVariable, false);
codeStream.jsr(subRoutineStartLabel);
+ codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+ int position = codeStream.position;
codeStream.load(anyExceptionVariable);
codeStream.athrow();
+ codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
subRoutineStartLabel.place();
codeStream.incrStackSize(1);
+ position = codeStream.position;
codeStream.store(returnAddressVariable, false);
- codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+ codeStream.recordPositionsFrom(position, finallyBlock.sourceStart);
finallyBlock.generateCode(scope, codeStream);
- int position = codeStream.position;
+ position = codeStream.position;
codeStream.ret(returnAddressVariable.resolvedPosition);
- codeStream.updateLastRecordedEndPC(position);
+// codeStream.updateLastRecordedEndPC(position);
codeStream.recordPositionsFrom(
position,
finallyBlock.sourceEnd);
// the ret bytecode is part of the subroutine
break;
-
case FINALLY_MUST_BE_INLINED :
codeStream.store(anyExceptionVariable, false);
+ codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
this.finallyBlock.generateCode(currentScope, codeStream);
+ position = codeStream.position;
codeStream.load(anyExceptionVariable);
codeStream.athrow();
subRoutineStartLabel.place();
- codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+ codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
break;
-
case FINALLY_DOES_NOT_COMPLETE :
codeStream.pop();
subRoutineStartLabel.place();
@@ -366,30 +360,25 @@ public class TryStatement extends SubRoutineStatement {
naturalExitLabel.place();
if (requiresNaturalExit) {
switch(finallyMode) {
-
case FINALLY_SUBROUTINE :
- int position = codeStream.position;
+ int position = codeStream.position;
// fix up natural exit handler
naturalExitExceptionHandler.placeStart();
codeStream.jsr(subRoutineStartLabel);
naturalExitExceptionHandler.placeEnd();
codeStream.recordPositionsFrom(
position,
- finallyBlock.sourceStart);
+ finallyBlock.sourceEnd);
break;
-
case FINALLY_MUST_BE_INLINED :
// May loose some local variable initializations : affecting the local variable attributes
// needed since any exception handler got inlined subroutine
if (preTryInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preTryInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
}
// entire sequence for finally is associated to finally block
finallyBlock.generateCode(scope, codeStream);
break;
-
case FINALLY_DOES_NOT_COMPLETE :
break;
}
@@ -406,9 +395,7 @@ public class TryStatement extends SubRoutineStatement {
}
// May loose some local variable initializations : affecting the local variable attributes
if (mergedInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- mergedInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -480,14 +467,14 @@ public class TryStatement extends SubRoutineStatement {
this.returnAddressVariable =
new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
finallyScope.addLocalVariable(returnAddressVariable);
- this.returnAddressVariable.constant = NotAConstant; // not inlinable
+ this.returnAddressVariable.setConstant(NotAConstant); // not inlinable
}
this.subRoutineStartLabel = new Label();
this.anyExceptionVariable =
new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
finallyScope.addLocalVariable(this.anyExceptionVariable);
- this.anyExceptionVariable.constant = NotAConstant; // not inlinable
+ this.anyExceptionVariable.setConstant(NotAConstant); // not inlinable
if (!methodScope.isInsideInitializer()) {
MethodBinding methodBinding =
@@ -502,7 +489,7 @@ public class TryStatement extends SubRoutineStatement {
AccDefault,
false);
finallyScope.addLocalVariable(this.secretReturnValue);
- this.secretReturnValue.constant = NotAConstant; // not inlinable
+ this.secretReturnValue.setConstant(NotAConstant); // not inlinable
}
}
}
@@ -518,17 +505,21 @@ public class TryStatement extends SubRoutineStatement {
if (this.catchBlocks != null) {
int length = this.catchArguments.length;
TypeBinding[] argumentTypes = new TypeBinding[length];
+ boolean catchHasError = false;
for (int i = 0; i < length; i++) {
BlockScope catchScope = new BlockScope(scope);
if (finallyScope != null){
finallyScope.shiftScopes[i+1] = catchScope;
}
// side effect on catchScope in resolveForCatch(..)
- if ((argumentTypes[i] = catchArguments[i].resolveForCatch(catchScope)) == null)
- return;
+ if ((argumentTypes[i] = catchArguments[i].resolveForCatch(catchScope)) == null) {
+ catchHasError = true;
+ }
catchBlocks[i].resolveUsing(catchScope);
}
-
+ if (catchHasError) {
+ return;
+ }
// Verify that the catch clause are ordered in the right way:
// more specialized first.
this.caughtExceptionTypes = new ReferenceBinding[length];
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index b6ba6f1..580877d 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -15,6 +15,7 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
@@ -28,6 +29,7 @@ public class TypeDeclaration
public int modifiers = AccDefault;
public int modifiersSourceStart;
+ public Annotation[] annotations;
public char[] name;
public TypeReference superclass;
public TypeReference[] superInterfaces;
@@ -46,12 +48,17 @@ public class TypeDeclaration
public int bodyEnd; // doesn't include the trailing comment if any.
protected boolean hasBeenGenerated = false;
public CompilationResult compilationResult;
- private MethodDeclaration[] missingAbstractMethods;
+ public MethodDeclaration[] missingAbstractMethods;
public Javadoc javadoc;
public QualifiedAllocationExpression allocation; // for anonymous only
public TypeDeclaration enclosingType; // for member types only
+ public FieldBinding enumValuesSyntheticfield; // for enum
+
+ // 1.5 support
+ public TypeParameter[] typeParameters;
+
public TypeDeclaration(CompilationResult compilationResult){
this.compilationResult = compilationResult;
}
@@ -282,7 +289,7 @@ public class TypeDeclaration
methods[i] = m;
}
} else {
- if (this.isInterface()) {
+ if (this.kind() == IGenericType.INTERFACE_DECL) {
// report the problem and continue the parsing
parser.problemReporter().interfaceCannotHaveConstructors(
(ConstructorDeclaration) am);
@@ -300,7 +307,7 @@ public class TypeDeclaration
return this.compilationResult;
}
- public ConstructorDeclaration createsInternalConstructor(
+ public ConstructorDeclaration createDefaultConstructor(
boolean needExplicitConstructorCall,
boolean needToInsert) {
@@ -312,7 +319,7 @@ public class TypeDeclaration
//the constructor
ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
constructor.isDefaultConstructor = true;
- constructor.selector = name;
+ constructor.selector = this.name;
if (modifiers != AccDefault) {
constructor.modifiers =
(((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
@@ -353,7 +360,7 @@ public class TypeDeclaration
}
// anonymous type constructor creation
- public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+ public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
//Add to method'set, the default constuctor that just recall the
//super constructor with the same arguments
@@ -550,10 +557,7 @@ public class TypeDeclaration
methods[i].generateCode(scope, classFile);
}
}
-
- classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
-
- // generate all methods
+ // generate all synthetic and abstract methods
classFile.addSpecialMethods();
if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
@@ -660,14 +664,14 @@ public class TypeDeclaration
if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
initializerScope.problemReporter().initializerMustCompleteNormally(field);
nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
- }
+ }
}
}
}
if (memberTypes != null) {
for (int i = 0, count = memberTypes.length; i < count; i++) {
if (flowContext != null){ // local type
- memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
+ memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
} else {
memberTypes[i].analyseCode(scope);
}
@@ -684,23 +688,32 @@ public class TypeDeclaration
if (method.isStatic()) { //
method.analyseCode(
scope,
- staticInitializerContext,
- staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
+ staticInitializerContext,
+ staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo).setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
} else { // constructor
- method.analyseCode(scope, initializerContext, constructorInfo.copy());
+ method.analyseCode(scope, initializerContext, constructorInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
}
} else { // regular method
method.analyseCode(scope, null, flowInfo.copy());
}
}
}
+ // enable enum support ?
+ if (this.binding.isEnum()) {
+ this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues();
+ }
}
- public boolean isInterface() {
-
- return (modifiers & AccInterface) != 0;
+ public int kind() {
+ if ((modifiers & AccInterface) != 0) {
+ if ((modifiers & AccAnnotation) != 0)
+ return IGenericType.ANNOTATION_TYPE_DECL;
+ return IGenericType.INTERFACE_DECL;
+ } else if ((modifiers & AccEnum) != 0)
+ return IGenericType.ENUM_DECL;
+ return IGenericType.CLASS_DECL;
}
-
+
/*
* Access emulation for a local type
* force to emulation of access to direct enclosing instance.
@@ -721,7 +734,7 @@ public class TypeDeclaration
}
// add superclass enclosing instance arg for anonymous types (if necessary)
if (binding.isAnonymousType()) {
- ReferenceBinding superclassBinding = binding.superclass;
+ ReferenceBinding superclassBinding = (ReferenceBinding)binding.superclass.erasure();
if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
if (!superclassBinding.isLocalType()
|| ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
@@ -759,12 +772,15 @@ public class TypeDeclaration
return true;
if (fields == null)
return false;
- if (isInterface())
+
+ if (kind() == IGenericType.INTERFACE_DECL)
return true; // fields are implicitly statics
for (int i = fields.length; --i >= 0;) {
FieldDeclaration field = fields[i];
//need to test the modifier directly while there is no binding yet
if ((field.modifiers & AccStatic) != 0)
+ return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
+ if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT)
return true;
}
return false;
@@ -786,16 +802,20 @@ public class TypeDeclaration
//methods
if (methods != null) {
int length = methods.length;
- for (int i = 0; i < length; i++)
+ for (int i = 0; i < length; i++) {
methods[i].parseStatements(parser, unit);
+ }
}
//initializers
if (fields != null) {
int length = fields.length;
for (int i = 0; i < length; i++) {
- if (fields[i] instanceof Initializer) {
- ((Initializer) fields[i]).parseStatements(parser, this, unit);
+ final FieldDeclaration fieldDeclaration = fields[i];
+ switch(fieldDeclaration.getKind()) {
+ case AbstractVariableDeclaration.INITIALIZER:
+ ((Initializer) fieldDeclaration).parseStatements(parser, this, unit);
+ break;
}
}
}
@@ -823,7 +843,7 @@ public class TypeDeclaration
}
if (fields != null) {
for (int fieldI = 0; fieldI < fields.length; fieldI++) {
- if (fields[fieldI] != null) {
+ if (fields[fieldI] != null) { // TODO (olivier) should improve to deal with enumconstants using ',' separator
output.append('\n');
fields[fieldI].print(indent + 1, output);
}
@@ -844,14 +864,46 @@ public class TypeDeclaration
public StringBuffer printHeader(int indent, StringBuffer output) {
printModifiers(this.modifiers, output);
- output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+ if (this.annotations != null) printAnnotations(this.annotations, output);
+
+ switch (kind()) {
+ case IGenericType.CLASS_DECL :
+ output.append("class "); //$NON-NLS-1$
+ break;
+ case IGenericType.INTERFACE_DECL :
+ output.append("interface "); //$NON-NLS-1$
+ break;
+ case IGenericType.ENUM_DECL :
+ output.append("enum "); //$NON-NLS-1$
+ break;
+ case IGenericType.ANNOTATION_TYPE_DECL :
+ output.append("@interface "); //$NON-NLS-1$
+ break;
+ }
output.append(name);
+ if (typeParameters != null) {
+ output.append("<");//$NON-NLS-1$
+ for (int i = 0; i < typeParameters.length; i++) {
+ if (i > 0) output.append( ", "); //$NON-NLS-1$
+ typeParameters[i].print(0, output);
+ }
+ output.append(">");//$NON-NLS-1$
+ }
if (superclass != null) {
output.append(" extends "); //$NON-NLS-1$
superclass.print(0, output);
}
if (superInterfaces != null && superInterfaces.length > 0) {
- output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+ switch (kind()) {
+ case IGenericType.CLASS_DECL :
+ case IGenericType.ENUM_DECL :
+ output.append(" implements "); //$NON-NLS-1$
+ break;
+ case IGenericType.INTERFACE_DECL :
+ case IGenericType.ANNOTATION_TYPE_DECL :
+ output.append(" extends "); //$NON-NLS-1$
+ break;
+ }
for (int i = 0; i < superInterfaces.length; i++) {
if (i > 0) output.append( ", "); //$NON-NLS-1$
superInterfaces[i].print(0, output);
@@ -863,51 +915,92 @@ public class TypeDeclaration
public StringBuffer printStatement(int tab, StringBuffer output) {
return print(tab, output);
}
+
- public void resolve() {
- if (this.binding == null) {
+ public void resolve() {
+ SourceTypeBinding sourceType = this.binding;
+ if (sourceType == null) {
this.ignoreFurtherInvestigation = true;
return;
}
try {
+ resolveAnnotations(this.staticInitializerScope, this.annotations, sourceType);
+
if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
}
- // check superclass & interfaces
- if (this.binding.superclass != null) // watch out for Object ! (and other roots)
- if (isTypeUseDeprecated(this.binding.superclass, this.scope))
- this.scope.problemReporter().deprecatedType(this.binding.superclass, this.superclass);
- if (this.superInterfaces != null)
- for (int i = this.superInterfaces.length; --i >= 0;)
- if (this.superInterfaces[i].resolvedType != null)
- if (isTypeUseDeprecated(this.superInterfaces[i].resolvedType, this.scope))
- this.scope.problemReporter().deprecatedType(
- this.superInterfaces[i].resolvedType,
- this.superInterfaces[i]);
+ boolean needSerialVersion =
+ this.scope.environment().options.getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore
+ && sourceType.isClass()
+ && !sourceType.isAbstract()
+ && sourceType.findSuperTypeErasingTo(T_JavaIoSerializable, false /*Serializable is not a class*/) != null;
+
+ if (this.typeParameters != null && scope.getJavaLangThrowable().isSuperclassOf(sourceType)) {
+ this.scope.problemReporter().genericTypeCannotExtendThrowable(this);
+ }
this.maxFieldCount = 0;
int lastVisibleFieldID = -1;
+ boolean hasEnumConstants = false;
+ boolean hasEnumConstantsWithoutBody = false;
+ if (this.memberTypes != null) {
+ for (int i = 0, count = this.memberTypes.length; i < count; i++) {
+ this.memberTypes[i].resolve(this.scope);
+ }
+ }
if (this.fields != null) {
for (int i = 0, count = this.fields.length; i < count; i++) {
FieldDeclaration field = this.fields[i];
- if (field.isField()) {
- if (field.binding == null) {
- // still discover secondary errors
- if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
- this.ignoreFurtherInvestigation = true;
- continue;
- }
- this.maxFieldCount++;
- lastVisibleFieldID = field.binding.id;
- } else { // initializer
- ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
+ switch(field.getKind()) {
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ hasEnumConstants = true;
+ if (!(field.initialization instanceof QualifiedAllocationExpression))
+ hasEnumConstantsWithoutBody = true;
+ case AbstractVariableDeclaration.FIELD:
+ FieldBinding fieldBinding = field.binding;
+ if (fieldBinding == null) {
+ // still discover secondary errors
+ if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
+ this.ignoreFurtherInvestigation = true;
+ continue;
+ }
+ if (needSerialVersion
+ && ((fieldBinding.modifiers & (AccStatic | AccFinal)) == (AccStatic | AccFinal))
+ && CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name)
+ && BaseTypes.LongBinding == fieldBinding.type) {
+ needSerialVersion = false;
+ }
+ this.maxFieldCount++;
+ lastVisibleFieldID = field.binding.id;
+ break;
+
+ case AbstractVariableDeclaration.INITIALIZER:
+ ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
+ break;
}
field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
}
}
- if (this.memberTypes != null) {
- for (int i = 0, count = this.memberTypes.length; i < count; i++) {
- this.memberTypes[i].resolve(this.scope);
+ if (needSerialVersion) {
+ this.scope.problemReporter().missingSerialVersion(this);
+ }
+ // check extends/implements for annotation type
+ if (kind() == IGenericType.ANNOTATION_TYPE_DECL) {
+ if (this.superclass != null) {
+ this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperclass(this);
+ }
+ if (this.superInterfaces != null) {
+ this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperinterfaces(this);
+ }
+ }
+ // check enum abstract methods
+ if (kind() == IGenericType.ENUM_DECL && this.binding.isAbstract()) {
+ if (!hasEnumConstants || hasEnumConstantsWithoutBody) {
+ for (int i = 0, count = this.methods.length; i < count; i++) {
+ if (this.methods[i].isAbstract()) {
+ this.scope.problemReporter().enumAbstractMethodMustBeImplemented(this.methods[i]);
+ }
+ }
}
}
int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
@@ -926,8 +1019,8 @@ public class TypeDeclaration
if (this.scope != null) {
this.javadoc.resolve(this.scope);
}
- } else if (this.binding != null && !this.binding.isLocalType()) {
- this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+ } else if (sourceType != null && !sourceType.isLocalType()) {
+ this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, sourceType.modifiers);
}
} catch (AbortType e) {
@@ -988,33 +1081,44 @@ public class TypeDeclaration
return;
try {
if (visitor.visit(this, unitScope)) {
- if (superclass != null)
- superclass.traverse(visitor, scope);
- if (superInterfaces != null) {
- int superInterfaceLength = superInterfaces.length;
- for (int i = 0; i < superInterfaceLength; i++)
- superInterfaces[i].traverse(visitor, scope);
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
}
- if (memberTypes != null) {
- int memberTypesLength = memberTypes.length;
- for (int i = 0; i < memberTypesLength; i++)
- memberTypes[i].traverse(visitor, scope);
+ if (this.superclass != null)
+ this.superclass.traverse(visitor, scope);
+ if (this.superInterfaces != null) {
+ int length = this.superInterfaces.length;
+ for (int i = 0; i < length; i++)
+ this.superInterfaces[i].traverse(visitor, scope);
}
- if (fields != null) {
- int fieldsLength = fields.length;
- for (int i = 0; i < fieldsLength; i++) {
+ if (this.typeParameters != null) {
+ int length = this.typeParameters.length;
+ for (int i = 0; i < length; i++) {
+ this.typeParameters[i].traverse(visitor, scope);
+ }
+ }
+ if (this.memberTypes != null) {
+ int length = this.memberTypes.length;
+ for (int i = 0; i < length; i++)
+ this.memberTypes[i].traverse(visitor, scope);
+ }
+ if (this.fields != null) {
+ int length = this.fields.length;
+ for (int i = 0; i < length; i++) {
FieldDeclaration field;
- if ((field = fields[i]).isStatic()) {
+ if ((field = this.fields[i]).isStatic()) {
field.traverse(visitor, staticInitializerScope);
} else {
field.traverse(visitor, initializerScope);
}
}
}
- if (methods != null) {
- int methodsLength = methods.length;
- for (int i = 0; i < methodsLength; i++)
- methods[i].traverse(visitor, scope);
+ if (this.methods != null) {
+ int length = this.methods.length;
+ for (int i = 0; i < length; i++)
+ this.methods[i].traverse(visitor, scope);
}
}
visitor.endVisit(this, unitScope);
@@ -1032,33 +1136,44 @@ public class TypeDeclaration
return;
try {
if (visitor.visit(this, blockScope)) {
- if (superclass != null)
- superclass.traverse(visitor, scope);
- if (superInterfaces != null) {
- int superInterfaceLength = superInterfaces.length;
- for (int i = 0; i < superInterfaceLength; i++)
- superInterfaces[i].traverse(visitor, scope);
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
+ }
+ if (this.superclass != null)
+ this.superclass.traverse(visitor, scope);
+ if (this.superInterfaces != null) {
+ int length = this.superInterfaces.length;
+ for (int i = 0; i < length; i++)
+ this.superInterfaces[i].traverse(visitor, scope);
}
- if (memberTypes != null) {
- int memberTypesLength = memberTypes.length;
- for (int i = 0; i < memberTypesLength; i++)
- memberTypes[i].traverse(visitor, scope);
+ if (this.typeParameters != null) {
+ int length = this.typeParameters.length;
+ for (int i = 0; i < length; i++) {
+ this.typeParameters[i].traverse(visitor, scope);
+ }
+ }
+ if (this.memberTypes != null) {
+ int length = this.memberTypes.length;
+ for (int i = 0; i < length; i++)
+ this.memberTypes[i].traverse(visitor, scope);
}
- if (fields != null) {
- int fieldsLength = fields.length;
- for (int i = 0; i < fieldsLength; i++) {
+ if (this.fields != null) {
+ int length = this.fields.length;
+ for (int i = 0; i < length; i++) {
FieldDeclaration field;
- if ((field = fields[i]).isStatic()) {
+ if ((field = this.fields[i]).isStatic()) {
// local type cannot have static fields
} else {
field.traverse(visitor, initializerScope);
}
}
}
- if (methods != null) {
- int methodsLength = methods.length;
- for (int i = 0; i < methodsLength; i++)
- methods[i].traverse(visitor, scope);
+ if (this.methods != null) {
+ int length = this.methods.length;
+ for (int i = 0; i < length; i++)
+ this.methods[i].traverse(visitor, scope);
}
}
visitor.endVisit(this, blockScope);
@@ -1076,33 +1191,44 @@ public class TypeDeclaration
return;
try {
if (visitor.visit(this, classScope)) {
- if (superclass != null)
- superclass.traverse(visitor, scope);
- if (superInterfaces != null) {
- int superInterfaceLength = superInterfaces.length;
- for (int i = 0; i < superInterfaceLength; i++)
- superInterfaces[i].traverse(visitor, scope);
+ if (this.annotations != null) {
+ int annotationsLength = this.annotations.length;
+ for (int i = 0; i < annotationsLength; i++)
+ this.annotations[i].traverse(visitor, scope);
}
- if (memberTypes != null) {
- int memberTypesLength = memberTypes.length;
- for (int i = 0; i < memberTypesLength; i++)
- memberTypes[i].traverse(visitor, scope);
+ if (this.superclass != null)
+ this.superclass.traverse(visitor, scope);
+ if (this.superInterfaces != null) {
+ int length = this.superInterfaces.length;
+ for (int i = 0; i < length; i++)
+ this.superInterfaces[i].traverse(visitor, scope);
+ }
+ if (this.typeParameters != null) {
+ int length = this.typeParameters.length;
+ for (int i = 0; i < length; i++) {
+ this.typeParameters[i].traverse(visitor, scope);
+ }
+ }
+ if (this.memberTypes != null) {
+ int length = this.memberTypes.length;
+ for (int i = 0; i < length; i++)
+ this.memberTypes[i].traverse(visitor, scope);
}
- if (fields != null) {
- int fieldsLength = fields.length;
- for (int i = 0; i < fieldsLength; i++) {
+ if (this.fields != null) {
+ int length = this.fields.length;
+ for (int i = 0; i < length; i++) {
FieldDeclaration field;
- if ((field = fields[i]).isStatic()) {
+ if ((field = this.fields[i]).isStatic()) {
field.traverse(visitor, staticInitializerScope);
} else {
field.traverse(visitor, initializerScope);
}
}
}
- if (methods != null) {
- int methodsLength = methods.length;
- for (int i = 0; i < methodsLength; i++)
- methods[i].traverse(visitor, scope);
+ if (this.methods != null) {
+ int length = this.methods.length;
+ for (int i = 0; i < length; i++)
+ this.methods[i].traverse(visitor, scope);
}
}
visitor.endVisit(this, classScope);
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java b/src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
new file mode 100644
index 0000000..bfa7e3f
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+
+public class TypeParameter extends AbstractVariableDeclaration {
+
+ public TypeVariableBinding binding;
+ public TypeReference[] bounds;
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
+ */
+ public int getKind() {
+ return TYPE_PARAMETER;
+ }
+
+ public void checkBounds(Scope scope) {
+
+ if (this.type != null) {
+ this.type.checkBounds(scope);
+ }
+ if (this.bounds != null) {
+ for (int i = 0, length = this.bounds.length; i < length; i++) {
+ this.bounds[i].checkBounds(scope);
+ }
+ }
+ }
+
+ public void resolve(ClassScope scope) {
+ // TODO (philippe) add warning for detecting variable name collisions
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.ast.AstNode#print(int, java.lang.StringBuffer)
+ */
+ public StringBuffer printStatement(int indent, StringBuffer output) {
+ output.append(this.name);
+ if (this.type != null) {
+ output.append(" extends "); //$NON-NLS-1$
+ this.type.print(0, output);
+ }
+ if (this.bounds != null){
+ for (int i = 0; i < this.bounds.length; i++) {
+ output.append(" & "); //$NON-NLS-1$
+ this.bounds[i].print(0, output);
+ }
+ }
+ return output;
+ }
+
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+ // nothing to do
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (type != null) {
+ type.traverse(visitor, scope);
+ }
+ if (bounds != null) {
+ int boundsLength = this.bounds.length;
+ for (int i = 0; i < boundsLength; i++) {
+ this.bounds[i].traverse(visitor, scope);
+ }
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (type != null) {
+ type.traverse(visitor, scope);
+ }
+ if (bounds != null) {
+ int boundsLength = this.bounds.length;
+ for (int i = 0; i < boundsLength; i++) {
+ this.bounds[i].traverse(visitor, scope);
+ }
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 2e8e10c..5865269 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -77,11 +77,21 @@ public static final TypeReference baseTypeReference(int baseType, int dim) {
return new ArrayTypeReference(LongBinding.simpleName, dim, 0);
}
}
+public void checkBounds(Scope scope) {
+ // only parameterized type references have bounds
+}
public abstract TypeReference copyDims(int dim);
public int dimensions() {
return 0;
}
-public abstract TypeBinding getTypeBinding(Scope scope);
+/**
+ * @return char[][]
+ * TODO (jerome) should merge back into #getTypeName()
+ */
+public char [][] getParameterizedTypeName(){
+ return getTypeName();
+}
+protected abstract TypeBinding getTypeBinding(Scope scope);
/**
* @return char[][]
*/
@@ -89,43 +99,65 @@ public abstract char [][] getTypeName() ;
public boolean isTypeReference() {
return true;
}
-public TypeBinding resolveType(BlockScope blockScope) {
- // handle the error here
- this.constant = NotAConstant;
- if (this.resolvedType != null) { // is a shared type reference which was already resolved
- if (!this.resolvedType.isValidBinding())
- return null; // already reported error
- } else {
- this.resolvedType = getTypeBinding(blockScope);
- if (!this.resolvedType.isValidBinding()) {
- reportInvalidType(blockScope);
- return null;
- }
- if (isTypeUseDeprecated(this.resolvedType, blockScope)) {
- reportDeprecatedType(blockScope);
- }
+public TypeBinding resolveSuperType(ClassScope scope) {
+ // assumes the implementation of resolveType(ClassScope) will call back to detect cycles
+ if (resolveType(scope) == null) return null;
+
+ if (this.resolvedType.isTypeVariable()) {
+ this.resolvedType = new ProblemReferenceBinding(getTypeName(), (ReferenceBinding) this.resolvedType, ProblemReasons.IllegalSuperTypeVariable);
+ reportInvalidType(scope);
+ return null;
}
return this.resolvedType;
}
+public final TypeBinding resolveType(BlockScope blockScope) {
+ return resolveType(blockScope, true /* checkbounds if any */);
+}
+
+public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) {
+ // handle the error here
+ this.constant = NotAConstant;
+ if (this.resolvedType != null) // is a shared type reference which was already resolved
+ return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+ this.resolvedType = getTypeBinding(blockScope);
+ if (this.resolvedType == null)
+ return null; // detected cycle while resolving hierarchy
+ if (!this.resolvedType.isValidBinding()) {
+ reportInvalidType(blockScope);
+ return null;
+ }
+ if (isTypeUseDeprecated(this.resolvedType, blockScope))
+ reportDeprecatedType(blockScope);
+ return this.resolvedType = blockScope.convertToRawType(this.resolvedType);
+}
public TypeBinding resolveType(ClassScope classScope) {
// handle the error here
this.constant = NotAConstant;
- if (this.resolvedType != null) { // is a shared type reference which was already resolved
- if (!this.resolvedType.isValidBinding())
- return null; // already reported error
- } else {
- this.resolvedType = getTypeBinding(classScope);
- if (!this.resolvedType.isValidBinding()) {
- reportInvalidType(classScope);
- return null;
- }
- if (isTypeUseDeprecated(this.resolvedType, classScope)) {
- reportDeprecatedType(classScope);
- }
+ if (this.resolvedType != null) // is a shared type reference which was already resolved
+ return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
+
+ this.resolvedType = getTypeBinding(classScope);
+ if (this.resolvedType == null)
+ return null; // detected cycle while resolving hierarchy
+ if (!this.resolvedType.isValidBinding()) {
+ reportInvalidType(classScope);
+ return null;
}
- return this.resolvedType;
+ if (isTypeUseDeprecated(this.resolvedType, classScope))
+ reportDeprecatedType(classScope);
+ return this.resolvedType = classScope.convertToRawType(this.resolvedType);
+}
+
+public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
+ return resolveType(blockScope, true /* check bounds*/);
}
+
+public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
+ return resolveType(classScope);
+}
+
protected void reportInvalidType(Scope scope) {
scope.problemReporter().invalidType(this, this.resolvedType);
}
@@ -133,4 +165,5 @@ protected void reportDeprecatedType(Scope scope) {
scope.problemReporter().deprecatedType(this.resolvedType, this);
}
public abstract void traverse(ASTVisitor visitor, ClassScope classScope);
+public abstract void traverse(ASTVisitor visitor, BlockScope classScope);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index 1e3a2fc..7e38c26 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -71,7 +71,7 @@ public class UnaryExpression extends OperatorExpression {
}
switch ((bits & OperatorMASK) >> OperatorSHIFT) {
case NOT :
- switch (this.expression.implicitConversion >> 4) /* runtime type */ {
+ switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) /* runtime type */ {
case T_boolean :
// !
// Generate code for the condition
@@ -97,8 +97,7 @@ public class UnaryExpression extends OperatorExpression {
}
break;
case TWIDDLE :
- switch (this.expression.implicitConversion >> 4 /* runtime */
- ) {
+ switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4 /* runtime */) {
case T_int :
// ~int
this.expression.generateCode(currentScope, codeStream, valueRequired);
@@ -119,7 +118,7 @@ public class UnaryExpression extends OperatorExpression {
// -
if (this.constant != NotAConstant) {
if (valueRequired) {
- switch (this.expression.implicitConversion >> 4){ /* runtime */
+ switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */
case T_int :
codeStream.generateInlinedValue(this.constant.intValue() * -1);
break;
@@ -136,7 +135,7 @@ public class UnaryExpression extends OperatorExpression {
} else {
this.expression.generateCode(currentScope, codeStream, valueRequired);
if (valueRequired) {
- switch (expression.implicitConversion >> 4){ /* runtime type */
+ switch ((expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime type */
case T_int :
codeStream.ineg();
break;
@@ -213,8 +212,16 @@ public class UnaryExpression extends OperatorExpression {
this.constant = NotAConstant;
return null;
}
- int expressionTypeId = expressionType.id;
- if (expressionTypeId > 15) {
+ int expressionTypeID = expressionType.id;
+ // autoboxing support
+ LookupEnvironment env = scope.environment();
+ boolean use15specifics = env.options.sourceLevel >= JDK1_5;
+ if (use15specifics) {
+ if (!expressionType.isBaseType()) {
+ expressionTypeID = env.computeBoxingType(expressionType).id;
+ }
+ }
+ if (expressionTypeID > 15) {
this.constant = NotAConstant;
scope.problemReporter().invalidOperator(this, expressionType);
return null;
@@ -236,8 +243,8 @@ public class UnaryExpression extends OperatorExpression {
// (cast) left Op (cast) rigth --> result
// 0000 0000 0000 0000 0000
// <<16 <<12 <<8 <<4 <<0
- int operatorSignature = OperatorSignatures[tableId][(expressionTypeId << 4) + expressionTypeId];
- this.expression.implicitConversion = operatorSignature >>> 12;
+ int operatorSignature = OperatorSignatures[tableId][(expressionTypeID << 4) + expressionTypeID];
+ this.expression.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), expressionType);
this.bits |= operatorSignature & 0xF;
switch (operatorSignature & 0xF) { // only switch on possible result type.....
case T_boolean :
@@ -263,7 +270,7 @@ public class UnaryExpression extends OperatorExpression {
break;
default : //error........
this.constant = Constant.NotAConstant;
- if (expressionTypeId != T_undefined)
+ if (expressionTypeID != T_undefined)
scope.problemReporter().invalidOperator(this, expressionType);
return null;
}
@@ -272,7 +279,7 @@ public class UnaryExpression extends OperatorExpression {
this.constant =
Constant.computeConstantOperation(
this.expression.constant,
- expressionTypeId,
+ expressionTypeID,
(bits & OperatorMASK) >> OperatorSHIFT);
} else {
this.constant = Constant.NotAConstant;
@@ -284,7 +291,7 @@ public class UnaryExpression extends OperatorExpression {
}
if (expressionIsCast) {
// check need for operand cast
- CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeId);
+ CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeID);
}
return this.resolvedType;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/src/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index b7e1441..fc7be36 100644
--- a/src/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/src/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -55,22 +55,23 @@ public class WhileStatement extends Statement {
preCondInitStateIndex =
currentScope.methodScope().recordInitializationStates(flowInfo);
LoopingFlowContext condLoopContext;
- FlowInfo postCondInfo =
- this.condition.analyseCode(
+ FlowInfo condInfo = flowInfo.copy().unconditionalInits().discardNullRelatedInitializations();
+ condInfo = this.condition.analyseCode(
currentScope,
(condLoopContext =
new LoopingFlowContext(flowContext, this, null, null, currentScope)),
- flowInfo);
+ condInfo);
LoopingFlowContext loopingContext;
FlowInfo actionInfo;
+ FlowInfo exitBranch;
if (action == null
|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
- condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+ condLoopContext.complainOnDeferredChecks(currentScope, condInfo);
if (isConditionTrue) {
return FlowInfo.DEAD_END;
} else {
- FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
+ FlowInfo mergedInfo = condInfo.initsWhenFalse().unconditionalInits();
if (isConditionOptimizedTrue){
mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
}
@@ -91,7 +92,7 @@ public class WhileStatement extends Statement {
if (isConditionFalse) {
actionInfo = FlowInfo.DEAD_END;
} else {
- actionInfo = postCondInfo.initsWhenTrue().copy();
+ actionInfo = condInfo.initsWhenTrue().copy();
if (isConditionOptimizedFalse){
actionInfo.setReachMode(FlowInfo.UNREACHABLE);
}
@@ -100,20 +101,22 @@ public class WhileStatement extends Statement {
// for computing local var attributes
condIfTrueInitStateIndex =
currentScope.methodScope().recordInitializationStates(
- postCondInfo.initsWhenTrue());
+ condInfo.initsWhenTrue());
if (!this.action.complainIfUnreachable(actionInfo, currentScope, false)) {
actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo);
}
// code generation can be optimized when no need to continue in the loop
+ exitBranch = condInfo.initsWhenFalse();
+ exitBranch.addInitializationsFrom(flowInfo); // recover null inits from before condition analysis
if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
continueLabel = null;
} else {
- // TODO (philippe) should simplify in one Loop context
- condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+ condLoopContext.complainOnDeferredChecks(currentScope, condInfo);
actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
- loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
+ loopingContext.complainOnDeferredChecks(currentScope, actionInfo);
+ exitBranch.addPotentialInitializationsFrom(actionInfo.unconditionalInits());
}
}
@@ -121,7 +124,7 @@ public class WhileStatement extends Statement {
FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
loopingContext.initsOnBreak,
isConditionOptimizedTrue,
- postCondInfo.initsWhenFalse(),
+ exitBranch,
isConditionOptimizedFalse,
!isConditionTrue /*while(true); unreachable(); */);
mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
@@ -178,9 +181,7 @@ public class WhileStatement extends Statement {
action.generateCode(currentScope, codeStream);
// May loose some local variable initializations : affecting the local variable attributes
if (preCondInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- preCondInitStateIndex);
+ codeStream.removeNotDefinitelyAssignedVariables(currentScope, preCondInitStateIndex);
}
}
@@ -207,7 +208,7 @@ public class WhileStatement extends Statement {
public void resolve(BlockScope scope) {
TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
- condition.implicitWidening(type, type);
+ condition.computeConversion(scope, type, type);
if (action != null)
action.resolve(scope);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
new file mode 100644
index 0000000..8c99f7d
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Node to represent Wildcard
+ */
+public class Wildcard extends SingleTypeReference {
+
+ public static final int UNBOUND = 0;
+ public static final int EXTENDS = 1;
+ public static final int SUPER = 2;
+
+ public TypeReference bound;
+ public int kind;
+
+ public Wildcard(int kind) {
+ super(WILDCARD_NAME, 0);
+ this.kind = kind;
+ }
+
+ public char [][] getParameterizedTypeName() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return new char[][] { WILDCARD_NAME };
+ case Wildcard.EXTENDS :
+ return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, CharOperation.concatWith(this.bound.getParameterizedTypeName(), '.')) };
+ default: // SUPER
+ return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, CharOperation.concatWith(this.bound.getParameterizedTypeName(), '.')) };
+ }
+ }
+
+ public char [][] getTypeName() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return new char[][] { WILDCARD_NAME };
+ case Wildcard.EXTENDS :
+ return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, CharOperation.concatWith(this.bound.getTypeName(), '.')) };
+ default: // SUPER
+ return new char[][] { CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, CharOperation.concatWith(this.bound.getTypeName(), '.')) };
+ }
+ }
+
+ private TypeBinding internalResolveType(Scope scope, ReferenceBinding genericType, int rank) {
+ TypeBinding boundType = null;
+ if (this.bound != null) {
+ boundType = scope.kind == Scope.CLASS_SCOPE
+ ? this.bound.resolveType((ClassScope)scope)
+ : this.bound.resolveType((BlockScope)scope, true /* check bounds*/);
+
+ if (boundType == null) {
+ return null;
+ }
+ }
+ WildcardBinding wildcard = scope.environment().createWildcard(genericType, rank, boundType, this.kind);
+ return this.resolvedType = wildcard;
+ }
+
+ public StringBuffer printExpression(int indent, StringBuffer output){
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ output.append(WILDCARD_NAME);
+ break;
+ case Wildcard.EXTENDS :
+ output.append(WILDCARD_NAME).append(WILDCARD_EXTENDS);
+ this.bound.printExpression(0, output);
+ break;
+ default: // SUPER
+ output.append(WILDCARD_NAME).append(WILDCARD_SUPER);
+ this.bound.printExpression(0, output);
+ break;
+ }
+ return output;
+ }
+
+ public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
+ return internalResolveType(blockScope, genericType, rank);
+ }
+
+ public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
+ return internalResolveType(classScope, genericType, rank);
+ }
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.bound != null) {
+ this.bound.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+
+ public void traverse(ASTVisitor visitor, ClassScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.bound != null) {
+ this.bound.traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 127b0cd..57b09e0 100644
--- a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -59,5 +59,14 @@ public interface ClassFileConstants extends IConstants {
// jdk level used to denote future releases: optional behavior is not enabled for now, but may become so. In order to enable these,
// search for references to this constant, and change it to one of the official JDT constants above.
- long JDK_DEFERRED = Long.MAX_VALUE;
+ long JDK_DEFERRED = Long.MAX_VALUE;
+
+ int INT_ARRAY = 10;
+ int BYTE_ARRAY = 8;
+ int BOOLEAN_ARRAY = 4;
+ int SHORT_ARRAY = 9;
+ int CHAR_ARRAY = 5;
+ int LONG_ARRAY = 11;
+ int FLOAT_ARRAY = 6;
+ int DOUBLE_ARRAY = 7;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index 6899fa0..fea4ef4 100644
--- a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -14,33 +14,88 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
+import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.util.Util;
public class ClassFileReader extends ClassFileStruct implements AttributeNamesConstants, IBinaryType {
- private int constantPoolCount;
- private int[] constantPoolOffsets;
- private long version;
+public static ClassFileReader read(File file) throws ClassFormatException, IOException {
+ return read(file, false);
+}
+public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
+ byte classFileBytes[] = Util.getFileByteContent(file);
+ ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
+ if (fullyInitialize) {
+ classFileReader.initialize();
+ }
+ return classFileReader;
+}
+public static ClassFileReader read(
+ java.util.zip.ZipFile zip,
+ String filename)
+ throws ClassFormatException, java.io.IOException {
+ return read(zip, filename, false);
+}
+public static ClassFileReader read(
+ java.util.zip.ZipFile zip,
+ String filename,
+ boolean fullyInitialize)
+ throws ClassFormatException, java.io.IOException {
+ java.util.zip.ZipEntry ze = zip.getEntry(filename);
+ if (ze == null)
+ return null;
+ byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip);
+ ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray());
+ if (fullyInitialize) {
+ classFileReader.initialize();
+ }
+ return classFileReader;
+}
+public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException {
+ return read(fileName, false);
+}
+public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException {
+ return read(new File(fileName), fullyInitialize);
+}
private int accessFlags;
+ private char[] classFileName;
private char[] className;
- private char[] superclassName;
- private int interfacesCount;
- private char[][] interfaceNames;
- private int fieldsCount;
+ private int classNameIndex;
+ private int constantPoolCount;
+ private int[] constantPoolOffsets;
private FieldInfo[] fields;
- private int methodsCount;
- private MethodInfo[] methods;
- private InnerClassInfo[] innerInfos;
- private char[] sourceFileName;
+ private int fieldsCount;
// initialized in case the .class file is a nested type
private InnerClassInfo innerInfo;
- private char[] classFileName;
- private int classNameIndex;
private int innerInfoIndex;
+ private InnerClassInfo[] innerInfos;
+ private char[][] interfaceNames;
+ private int interfacesCount;
+ private MethodInfo[] methods;
+ private int methodsCount;
+ private char[] signature;
+ private char[] sourceFileName;
+ private char[] superclassName;
+ private long tagBits;
+ private long version;
+
+/**
+ * @param classFileBytes Actual bytes of a .class file
+ * @param fileName Actual name of the file that contains the bytes, can be null
+ *
+ * @exception ClassFormatException
+ */
+public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException {
+ this(classFileBytes, fileName, false);
+}
+
/**
* @param classFileBytes byte[]
* Actual bytes of a .class file
@@ -176,35 +231,62 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit
for (int i = 0; i < attributesCount; i++) {
int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
- if (CharOperation.equals(attributeName, DeprecatedName)) {
- this.accessFlags |= AccDeprecated;
- } else {
- if (CharOperation.equals(attributeName, InnerClassName)) {
- int innerOffset = readOffset + 6;
- int number_of_classes = u2At(innerOffset);
- if (number_of_classes != 0) {
- innerOffset+= 2;
- this.innerInfos = new InnerClassInfo[number_of_classes];
- for (int j = 0; j < number_of_classes; j++) {
- this.innerInfos[j] =
- new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset);
- if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) {
- this.innerInfo = this.innerInfos[j];
- this.innerInfoIndex = j;
+ if (attributeName.length == 0) {
+ readOffset += (6 + u4At(readOffset + 2));
+ continue;
+ }
+ switch(attributeName[0] ) {
+ case 'D' :
+ if (CharOperation.equals(attributeName, DeprecatedName)) {
+ this.accessFlags |= AccDeprecated;
+ }
+ break;
+ case 'I' :
+ if (CharOperation.equals(attributeName, InnerClassName)) {
+ int innerOffset = readOffset + 6;
+ int number_of_classes = u2At(innerOffset);
+ if (number_of_classes != 0) {
+ innerOffset+= 2;
+ this.innerInfos = new InnerClassInfo[number_of_classes];
+ for (int j = 0; j < number_of_classes; j++) {
+ this.innerInfos[j] =
+ new InnerClassInfo(reference, this.constantPoolOffsets, innerOffset);
+ if (this.classNameIndex == this.innerInfos[j].innerClassNameIndex) {
+ this.innerInfo = this.innerInfos[j];
+ this.innerInfoIndex = j;
+ }
+ innerOffset += 8;
}
- innerOffset += 8;
}
}
- } else {
- if (CharOperation.equals(attributeName, SourceName)) {
- utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
- this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
- } else {
- if (CharOperation.equals(attributeName, SyntheticName)) {
- this.accessFlags |= AccSynthetic;
+ break;
+ case 'S' :
+ if (attributeName.length > 2) {
+ switch(attributeName[1]) {
+ case 'o' :
+ if (CharOperation.equals(attributeName, SourceName)) {
+ utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
+ this.sourceFileName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ }
+ break;
+ case 'y' :
+ if (CharOperation.equals(attributeName, SyntheticName)) {
+ this.accessFlags |= AccSynthetic;
+ }
+ break;
+ case 'i' :
+ if (CharOperation.equals(attributeName, SignatureName)) {
+ utf8Offset = this.constantPoolOffsets[u2At(readOffset + 6)];
+ this.signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ }
}
}
- }
+ break;
+ case 'R' :
+ if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+ decodeStandardAnnotations(readOffset);
+ }
+ break;
}
readOffset += (6 + u4At(readOffset + 2));
}
@@ -221,16 +303,6 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit
}
/**
- * @param classFileBytes Actual bytes of a .class file
- * @param fileName Actual name of the file that contains the bytes, can be null
- *
- * @exception ClassFormatException
- */
-public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassFormatException {
- this(classFileBytes, fileName, false);
-}
-
-/**
* Answer the receiver's access flags. The value of the access_flags
* item is a mask of modifiers used with class and interface declarations.
* @return int
@@ -238,6 +310,192 @@ public ClassFileReader(byte classFileBytes[], char[] fileName) throws ClassForma
public int accessFlags() {
return this.accessFlags;
}
+private int decodeAnnotation(int offset) {
+ int readOffset = offset;
+ int utf8Offset = this.constantPoolOffsets[u2At(offset)];
+ char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ typeName = Signature.toCharArray(typeName);
+ CharOperation.replace(typeName, '/', '.');
+ char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+ int numberOfPairs = u2At(offset + 2);
+ readOffset += 4;
+ switch(qualifiedTypeName.length) {
+ case 3 :
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+ this.tagBits |= TagBits.AnnotationDeprecated;
+ return readOffset;
+ }
+ break;
+ case 4 :
+ char[] lastPart = qualifiedTypeName[3];
+ if (lastPart.length > 0) {
+ switch(lastPart[0]) {
+ case 'R' :
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTION)) {
+ for (int i = 0; i < numberOfPairs; i++) {
+ readOffset += 2;
+ readOffset = decodeElementValueForJavaLangAnnotationRetention(readOffset);
+ }
+ return readOffset;
+ }
+ break;
+ case 'T' :
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_TARGET)) {
+ for (int i = 0; i < numberOfPairs; i++) {
+ readOffset += 2;
+ readOffset = decodeElementValueForJavaLangAnnotationTarget(readOffset);
+ }
+ return readOffset;
+ }
+ break;
+ case 'D' :
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED)) {
+ this.tagBits |= TagBits.AnnotationDocumented;
+ return readOffset;
+ }
+ break;
+ case 'I' :
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_ANNOTATION_INHERITED)) {
+ this.tagBits |= TagBits.AnnotationInherited;
+ return readOffset;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < numberOfPairs; i++) {
+ readOffset += 2;
+ readOffset = decodeElementValue(readOffset);
+ }
+ return readOffset;
+}
+private int decodeElementValue(int offset) {
+ int readOffset = offset;
+ int tag = u1At(readOffset);
+ readOffset++;
+ switch(tag) {
+ case 'B' :
+ case 'C' :
+ case 'D' :
+ case 'F' :
+ case 'I' :
+ case 'J' :
+ case 'S' :
+ case 'Z' :
+ case 's' :
+ readOffset += 2;
+ break;
+ case 'e' :
+ readOffset += 4;
+ break;
+ case 'c' :
+ readOffset += 2;
+ break;
+ case '@' :
+ readOffset += decodeAnnotation(readOffset);
+ break;
+ case '[' :
+ int numberOfValues = u2At(readOffset);
+ readOffset += 2;
+ for (int i = 0; i < numberOfValues; i++) {
+ readOffset = decodeElementValueForJavaLangAnnotationTarget(readOffset);
+ }
+ break;
+ }
+ return readOffset;
+}
+private int decodeElementValueForJavaLangAnnotationTarget(int offset) {
+ int readOffset = offset;
+ int tag = u1At(readOffset);
+ readOffset++;
+ switch(tag) {
+ case 'B' :
+ case 'C' :
+ case 'D' :
+ case 'F' :
+ case 'I' :
+ case 'J' :
+ case 'S' :
+ case 'Z' :
+ case 's' :
+ readOffset += 2;
+ break;
+ case 'e' :
+ readOffset += 2;
+ int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+ char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ readOffset += 2;
+ this.tagBits |= Annotation.getTargetElementType(constName);
+ break;
+ case 'c' :
+ readOffset += 2;
+ break;
+ case '@' :
+ readOffset += decodeAnnotation(readOffset);
+ break;
+ case '[' :
+ int numberOfValues = u2At(readOffset);
+ readOffset += 2;
+ if (numberOfValues == 0) {
+ this.tagBits |= TagBits.AnnotationTarget;
+ } else {
+ for (int i = 0; i < numberOfValues; i++) {
+ readOffset = decodeElementValueForJavaLangAnnotationTarget(readOffset);
+ }
+ }
+ break;
+ }
+ return readOffset;
+}
+private int decodeElementValueForJavaLangAnnotationRetention(int offset) {
+ int readOffset = offset;
+ int tag = u1At(readOffset);
+ readOffset++;
+ switch(tag) {
+ case 'B' :
+ case 'C' :
+ case 'D' :
+ case 'F' :
+ case 'I' :
+ case 'J' :
+ case 'S' :
+ case 'Z' :
+ case 's' :
+ readOffset += 2;
+ break;
+ case 'e' :
+ readOffset += 2;
+ int utf8Offset = this.constantPoolOffsets[u2At(readOffset)];
+ char[] constName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ readOffset += 2;
+ this.tagBits |= Annotation.getRetentionPolicy(constName);
+ break;
+ case 'c' :
+ readOffset += 2;
+ break;
+ case '@' :
+ readOffset += decodeAnnotation(readOffset);
+ break;
+ case '[' :
+ int numberOfValues = u2At(readOffset);
+ readOffset += 2;
+ for (int i = 0; i < numberOfValues; i++) {
+ readOffset = decodeElementValueForJavaLangAnnotationRetention(readOffset);
+ }
+ break;
+ }
+ return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+ int numberOfAnnotations = u2At(offset + 6);
+ int readOffset = offset + 8;
+ for (int i = 0; i < numberOfAnnotations; i++) {
+ readOffset = decodeAnnotation(readOffset);
+ }
+}
/**
* Answer the char array that corresponds to the class name of the constant class.
* constantPoolIndex is the index in the constant pool that is a constant class entry.
@@ -275,12 +533,14 @@ public IBinaryField[] getFields() {
return this.fields;
}
/**
- * Answer the file name which defines the type.
- * The format is unspecified.
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
*/
public char[] getFileName() {
return this.classFileName;
}
+public char[] getGenericSignature() {
+ return this.signature;
+}
/**
* Answer the source name if the receiver is a inner type. Return null if it is an anonymous class or if the receiver is a top-level class.
* e.g.
@@ -318,11 +578,25 @@ public char[] getInnerSourceName() {
public char[][] getInterfaceNames() {
return this.interfaceNames;
}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
+ */
+public int getKind() {
+ int modifiers = getModifiers();
+ if ((modifiers & AccInterface) != 0) {
+ if ((modifiers & AccAnnotation) != 0) return IGenericType.ANNOTATION_TYPE_DECL;
+ return IGenericType.INTERFACE_DECL;
+ }
+ if ((modifiers & AccEnum) != 0) return IGenericType.ENUM_DECL;
+ return IGenericType.CLASS_DECL;
+}
/**
* Answer the receiver's nested types or null if the array is empty.
- *
- * This nested type info is extracted from the inner class attributes.
- * Ask the name environment to find a member type using its compound name
+ *
+ * This nested type info is extracted from the inner class attributes. Ask the
+ * name environment to find a member type using its compound name
+ *
* @return org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[]
*/
public IBinaryNestedType[] getMemberTypes() {
@@ -389,11 +663,7 @@ public IBinaryMethod[] getMethods() {
*/
public int getModifiers() {
if (this.innerInfo != null) {
- if ((this.accessFlags & AccDeprecated) != 0) {
- return this.innerInfo.getModifiers() | AccDeprecated;
- } else {
- return this.innerInfo.getModifiers();
- }
+ return this.innerInfo.getModifiers() | (this.accessFlags & AccDeprecated);
}
return this.accessFlags;
}
@@ -418,6 +688,9 @@ public char[] getName() {
public char[] getSuperclassName() {
return this.superclassName;
}
+public long getTagBits() {
+ return this.tagBits;
+}
/**
* Answer the major/minor version defined in this class file according to the VM spec.
* as a long: (major<<16)+minor
@@ -426,126 +699,56 @@ public char[] getSuperclassName() {
public long getVersion() {
return this.version;
}
-/**
- * Answer true if the receiver is an anonymous type, false otherwise
- *
- * @return boolean
- */
-public boolean isAnonymous() {
- if (this.innerInfo == null) return false;
- char[] sourceName = this.innerInfo.getSourceName();
- return (sourceName == null || sourceName.length == 0);
-}
-/**
- * Answer whether the receiver contains the resolved binary form
- * or the unresolved source form of the type.
- * @return boolean
- */
-public boolean isBinaryType() {
- return true;
-}
-/**
- * Answer true if the receiver is a class. False otherwise.
- * @return boolean
- */
-public boolean isClass() {
- return (getModifiers() & AccInterface) == 0;
-}
-/**
- * Answer true if the receiver is an interface. False otherwise.
- * @return boolean
- */
-public boolean isInterface() {
- return (getModifiers() & AccInterface) != 0;
-}
-/**
- * Answer true if the receiver is a local type, false otherwise
- *
- * @return boolean
- */
-public boolean isLocal() {
- if (this.innerInfo == null) return false;
- if (this.innerInfo.getEnclosingTypeName() != null) return false;
- char[] sourceName = this.innerInfo.getSourceName();
- return (sourceName != null && sourceName.length > 0);
-}
-/**
- * Answer true if the receiver is a member type, false otherwise
- *
- * @return boolean
- */
-public boolean isMember() {
- if (this.innerInfo == null) return false;
- if (this.innerInfo.getEnclosingTypeName() == null) return false;
- char[] sourceName = this.innerInfo.getSourceName();
- return (sourceName != null && sourceName.length > 0); // protection against ill-formed attributes (67600)
-}
-/**
- * Answer true if the receiver is a nested type, false otherwise
- *
- * @return boolean
- */
-public boolean isNestedType() {
- return this.innerInfo != null;
-}
-public static ClassFileReader read(File file) throws ClassFormatException, IOException {
- return read(file, false);
-}
-public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
- byte classFileBytes[] = Util.getFileByteContent(file);
- ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
- if (fullyInitialize) {
- classFileReader.initialize();
+private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) {
+ int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length;
+ int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length;
+ int index1 = 0;
+ int index2 = 0;
+
+ end : while (index1 < length1 && index2 < length2) {
+ while (currentFieldInfos[index1].isSynthetic()) {
+ if (++index1 >= length1) break end;
+ }
+ while (otherFieldInfos[index2].isSynthetic()) {
+ if (++index2 >= length2) break end;
+ }
+ if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++]))
+ return true;
}
- return classFileReader;
-}
-public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException {
- return read(fileName, false);
-}
-public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException {
- return read(new File(fileName), fullyInitialize);
-}
-public static ClassFileReader read(
- java.util.zip.ZipFile zip,
- String filename)
- throws ClassFormatException, java.io.IOException {
- return read(zip, filename, false);
-}
-public static ClassFileReader read(
- java.util.zip.ZipFile zip,
- String filename,
- boolean fullyInitialize)
- throws ClassFormatException, java.io.IOException {
- java.util.zip.ZipEntry ze = zip.getEntry(filename);
- if (ze == null)
- return null;
- byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip);
- ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray());
- if (fullyInitialize) {
- classFileReader.initialize();
+
+ while (index1 < length1) {
+ if (!currentFieldInfos[index1++].isSynthetic()) return true;
}
- return classFileReader;
+ while (index2 < length2) {
+ if (!otherFieldInfos[index2++].isSynthetic()) return true;
+ }
+ return false;
}
+private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) {
+ int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length;
+ int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length;
+ int index1 = 0;
+ int index2 = 0;
-/**
- * Answer the source file name attribute. Return null if there is no source file attribute for the receiver.
- *
- * @return char[]
- */
-public char[] sourceFileName() {
- return this.sourceFileName;
-}
-public String toString() {
- java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
- java.io.PrintWriter print = new java.io.PrintWriter(out);
-
- print.println(this.getClass().getName() + "{"); //$NON-NLS-1$
- print.println(" this.className: " + new String(getName())); //$NON-NLS-1$
- print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$
- print.println(" access_flags: " + ClassFileStruct.printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+ MethodInfo m;
+ end : while (index1 < length1 && index2 < length2) {
+ while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) {
+ if (++index1 >= length1) break end;
+ }
+ while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) {
+ if (++index2 >= length2) break end;
+ }
+ if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++]))
+ return true;
+ }
- print.flush();
- return out.toString();
+ while (index1 < length1) {
+ if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true;
+ }
+ while (index2 < length2) {
+ if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true;
+ }
+ return false;
}
/**
* Check if the receiver has structural changes compare to the byte array in argument.
@@ -589,6 +792,11 @@ public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, bool
// modifiers
if (this.getModifiers() != newClassFile.getModifiers())
return true;
+
+ // meta-annotations
+ if ((this.getTagBits() & TagBits.AnnotationTargetMASK|TagBits.AnnotationDeprecated|TagBits.AnnotationRetentionMASK) != (newClassFile.getTagBits() & TagBits.AnnotationTargetMASK|TagBits.AnnotationDeprecated|TagBits.AnnotationRetentionMASK))
+ return true;
+
// superclass
if (!CharOperation.equals(this.getSuperclassName(), newClassFile.getSuperclassName()))
return true;
@@ -682,34 +890,11 @@ public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, bool
return true;
}
}
-private boolean hasNonSyntheticFieldChanges(FieldInfo[] currentFieldInfos, FieldInfo[] otherFieldInfos) {
- int length1 = currentFieldInfos == null ? 0 : currentFieldInfos.length;
- int length2 = otherFieldInfos == null ? 0 : otherFieldInfos.length;
- int index1 = 0;
- int index2 = 0;
-
- end : while (index1 < length1 && index2 < length2) {
- while (currentFieldInfos[index1].isSynthetic()) {
- if (++index1 >= length1) break end;
- }
- while (otherFieldInfos[index2].isSynthetic()) {
- if (++index2 >= length2) break end;
- }
- if (hasStructuralFieldChanges(currentFieldInfos[index1++], otherFieldInfos[index2++]))
- return true;
- }
-
- while (index1 < length1) {
- if (!currentFieldInfos[index1++].isSynthetic()) return true;
- }
- while (index2 < length2) {
- if (!otherFieldInfos[index2++].isSynthetic()) return true;
- }
- return false;
-}
private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo otherFieldInfo) {
if (currentFieldInfo.getModifiers() != otherFieldInfo.getModifiers())
return true;
+ if ((currentFieldInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherFieldInfo.getTagBits() & TagBits.AnnotationDeprecated))
+ return true;
if (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName()))
return true;
if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName()))
@@ -740,45 +925,23 @@ private boolean hasStructuralFieldChanges(FieldInfo currentFieldInfo, FieldInfo
return currentConstant.doubleValue() != otherConstant.doubleValue();
case TypeIds.T_boolean :
return currentConstant.booleanValue() != otherConstant.booleanValue();
- case TypeIds.T_String :
+ case TypeIds.T_JavaLangString :
return !currentConstant.stringValue().equals(otherConstant.stringValue());
}
}
return false;
}
-private boolean hasNonSyntheticMethodChanges(MethodInfo[] currentMethodInfos, MethodInfo[] otherMethodInfos) {
- int length1 = currentMethodInfos == null ? 0 : currentMethodInfos.length;
- int length2 = otherMethodInfos == null ? 0 : otherMethodInfos.length;
- int index1 = 0;
- int index2 = 0;
-
- MethodInfo m;
- end : while (index1 < length1 && index2 < length2) {
- while ((m = currentMethodInfos[index1]).isSynthetic() || m.isClinit()) {
- if (++index1 >= length1) break end;
- }
- while ((m = otherMethodInfos[index2]).isSynthetic() || m.isClinit()) {
- if (++index2 >= length2) break end;
- }
- if (hasStructuralMethodChanges(currentMethodInfos[index1++], otherMethodInfos[index2++]))
- return true;
- }
-
- while (index1 < length1) {
- if (!((m = currentMethodInfos[index1++]).isSynthetic() || m.isClinit())) return true;
- }
- while (index2 < length2) {
- if (!((m = otherMethodInfos[index2++]).isSynthetic() || m.isClinit())) return true;
- }
- return false;
-}
private boolean hasStructuralMethodChanges(MethodInfo currentMethodInfo, MethodInfo otherMethodInfo) {
if (currentMethodInfo.getModifiers() != otherMethodInfo.getModifiers())
return true;
+ if ((currentMethodInfo.getTagBits() & TagBits.AnnotationDeprecated) != (otherMethodInfo.getTagBits() & TagBits.AnnotationDeprecated))
+ return true;
if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
return true;
if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
return true;
+ if (!CharOperation.equals(currentMethodInfo.getGenericSignature(), otherMethodInfo.getGenericSignature()))
+ return true;
char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames();
char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames();
@@ -816,9 +979,75 @@ private void initialize() throws ClassFormatException {
throw exception;
}
}
+/**
+ * Answer true if the receiver is an anonymous type, false otherwise
+ *
+ * @return boolean
+ */
+public boolean isAnonymous() {
+ if (this.innerInfo == null) return false;
+ char[] sourceName = this.innerInfo.getSourceName();
+ return (sourceName == null || sourceName.length == 0);
+}
+/**
+ * Answer whether the receiver contains the resolved binary form
+ * or the unresolved source form of the type.
+ * @return boolean
+ */
+public boolean isBinaryType() {
+ return true;
+}
+
+/**
+ * Answer true if the receiver is a local type, false otherwise
+ *
+ * @return boolean
+ */
+public boolean isLocal() {
+ if (this.innerInfo == null) return false;
+ if (this.innerInfo.getEnclosingTypeName() != null) return false;
+ char[] sourceName = this.innerInfo.getSourceName();
+ return (sourceName != null && sourceName.length > 0);
+}
+/**
+ * Answer true if the receiver is a member type, false otherwise
+ *
+ * @return boolean
+ */
+public boolean isMember() {
+ if (this.innerInfo == null) return false;
+ if (this.innerInfo.getEnclosingTypeName() == null) return false;
+ char[] sourceName = this.innerInfo.getSourceName();
+ return (sourceName != null && sourceName.length > 0); // protection against ill-formed attributes (67600)
+}
+/**
+ * Answer true if the receiver is a nested type, false otherwise
+ *
+ * @return boolean
+ */
+public boolean isNestedType() {
+ return this.innerInfo != null;
+}
protected void reset() {
this.constantPoolOffsets = null;
super.reset();
}
-
+/**
+ * Answer the source file name attribute. Return null if there is no source file attribute for the receiver.
+ *
+ * @return char[]
+ */
+public char[] sourceFileName() {
+ return this.sourceFileName;
+}
+public String toString() {
+ java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+ java.io.PrintWriter print = new java.io.PrintWriter(out);
+ print.println(this.getClass().getName() + "{"); //$NON-NLS-1$
+ print.println(" this.className: " + new String(getName())); //$NON-NLS-1$
+ print.println(" this.superclassName: " + (getSuperclassName() == null ? "null" : new String(getSuperclassName()))); //$NON-NLS-2$ //$NON-NLS-1$
+ print.println(" access_flags: " + ClassFileStruct.printTypeModifiers(this.accessFlags()) + "(" + this.accessFlags() + ")"); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+ print.flush();
+ return out.toString();
+}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
index fd3f30e..019ff5e 100644
--- a/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
+++ b/src/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
@@ -10,6 +10,7 @@ package org.eclipse.jdt.internal.compiler.classfmt;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ClassFormatException extends Exception {
+
public static final int ErrBadMagic = 1;
public static final int ErrBadMinorVersion = 2;
public static final int ErrBadMajorVersion = 3;
diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index 26392d8..b986492 100644
--- a/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.classfmt;
+import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -23,18 +24,21 @@ import org.eclipse.jdt.internal.compiler.impl.IntConstant;
import org.eclipse.jdt.internal.compiler.impl.LongConstant;
import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.util.Util;
public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
+ private int accessFlags;
+ private int attributeBytes;
private Constant constant;
- private boolean isDeprecated;
- private boolean isSynthetic;
private int[] constantPoolOffsets;
- private int accessFlags;
+ private char[] descriptor;
private char[] name;
private char[] signature;
- private int attributeBytes;
+ private int signatureUtf8Offset;
+ private long tagBits;
private Object wrappedConstantValue;
/**
* @param classFileBytes byte[]
@@ -47,11 +51,105 @@ public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
accessFlags = -1;
int attributesCount = u2At(6);
int readOffset = 8;
+ this.signatureUtf8Offset = -1;
for (int i = 0; i < attributesCount; i++) {
+ // check the name of each attribute
+ int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+ char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ if (attributeName.length > 0) {
+ switch(attributeName[0]) {
+ case 'S' :
+ if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) {
+ this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+ }
+ break;
+ case 'R' :
+ if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+ decodeStandardAnnotations(readOffset);
+ }
+ }
+ }
readOffset += (6 + u4At(readOffset + 2));
}
attributeBytes = readOffset;
}
+
+public int compareTo(Object o) {
+ if (!(o instanceof FieldInfo)) {
+ throw new ClassCastException();
+ }
+ return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
+}
+private int decodeAnnotation(int offset) {
+ int readOffset = offset;
+ int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset;
+ char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ typeName = Signature.toCharArray(typeName);
+ CharOperation.replace(typeName, '/', '.');
+ char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+ int numberOfPairs = u2At(offset + 2);
+ readOffset += 4;
+ if (qualifiedTypeName.length == 3) {
+ char[] lastPart = qualifiedTypeName[2];
+ if (lastPart[0] == 'D') {
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+ this.tagBits |= TagBits.AnnotationDeprecated;
+ return readOffset;
+ }
+ }
+ }
+ for (int i = 0; i < numberOfPairs; i++) {
+ readOffset += 2;
+ readOffset = decodeElementValue(readOffset);
+ }
+ return readOffset;
+}
+private int decodeElementValue(int offset) {
+ int readOffset = offset;
+ int tag = u1At(readOffset);
+ readOffset++;
+ switch(tag) {
+ case 'B' :
+ case 'C' :
+ case 'D' :
+ case 'F' :
+ case 'I' :
+ case 'J' :
+ case 'S' :
+ case 'Z' :
+ case 's' :
+ readOffset += 2;
+ break;
+ case 'e' :
+ readOffset += 4;
+ break;
+ case 'c' :
+ readOffset += 2;
+ break;
+ case '@' :
+ readOffset += decodeAnnotation(readOffset);
+ break;
+ case '[' :
+ int numberOfValues = u2At(readOffset);
+ readOffset += 2;
+ for (int i = 0; i < numberOfValues; i++) {
+ readOffset = decodeElementValue(readOffset);
+ }
+ break;
+ }
+ return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+ int numberOfAnnotations = u2At(offset + 6);
+ int readOffset = offset + 8;
+ for (int i = 0; i < numberOfAnnotations; i++) {
+ readOffset = decodeAnnotation(readOffset);
+ }
+}
/**
* Return the constant of the field.
* Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
@@ -64,6 +162,16 @@ public Constant getConstant() {
}
return constant;
}
+public char[] getGenericSignature() {
+ if (this.signatureUtf8Offset != -1) {
+ if (this.signature == null) {
+ // decode the signature
+ this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
+ }
+ return this.signature;
+ }
+ return null;
+}
/**
* Answer an int whose bits are set according the access constants
* defined by the VM spec.
@@ -71,18 +179,12 @@ public Constant getConstant() {
* @return int
*/
public int getModifiers() {
- if (accessFlags == -1) {
+ if (this.accessFlags == -1) {
// compute the accessflag. Don't forget the deprecated attribute
- accessFlags = u2At(0);
- readDeprecatedAndSyntheticAttributes();
- if (isDeprecated) {
- accessFlags |= AccDeprecated;
- }
- if (isSynthetic) {
- accessFlags |= AccSynthetic;
- }
+ this.accessFlags = u2At(0);
+ readModifierRelatedAttributes();
}
- return accessFlags;
+ return this.accessFlags;
}
/**
* Answer the name of the field.
@@ -96,6 +198,9 @@ public char[] getName() {
}
return name;
}
+public long getTagBits() {
+ return this.tagBits;
+}
/**
* Answer the resolved name of the receiver's type in the
* class file format as specified in section 4.3.2 of the Java 2 VM spec.
@@ -108,12 +213,12 @@ public char[] getName() {
* @return char[]
*/
public char[] getTypeName() {
- if (signature == null) {
+ if (descriptor == null) {
// read the signature
int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
- signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
}
- return signature;
+ return descriptor;
}
/**
* Return a wrapper that contains the constant of the field.
@@ -149,7 +254,7 @@ public Object getWrappedConstantValue() {
case T_long :
this.wrappedConstantValue = new Long(fieldConstant.longValue());
break;
- case T_String :
+ case T_JavaLangString :
this.wrappedConstantValue = fieldConstant.stringValue();
}
}
@@ -164,6 +269,18 @@ public boolean hasConstant() {
return getConstant() != Constant.NotAConstant;
}
/**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+ getModifiers();
+ getName();
+ getConstant();
+ getTypeName();
+ getGenericSignature();
+ reset();
+}
+/**
* Return true if the field is a synthetic field, false otherwise.
* @return boolean
*/
@@ -233,20 +350,32 @@ private void readConstantAttribute() {
constant = Constant.NotAConstant;
}
}
-private void readDeprecatedAndSyntheticAttributes() {
+private void readModifierRelatedAttributes() {
int attributesCount = u2At(6);
int readOffset = 8;
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, DeprecatedName)) {
- isDeprecated = true;
- } else if (CharOperation.equals(attributeName, SyntheticName)) {
- isSynthetic = true;
+ // test added for obfuscated .class file. See 79772
+ if (attributeName.length != 0) {
+ switch(attributeName[0]) {
+ case 'D' :
+ if (CharOperation.equals(attributeName, DeprecatedName))
+ this.accessFlags |= AccDeprecated;
+ break;
+ case 'S' :
+ if (CharOperation.equals(attributeName, SyntheticName))
+ this.accessFlags |= AccSynthetic;
+ break;
+ }
}
readOffset += (6 + u4At(readOffset + 2));
}
}
+protected void reset() {
+ this.constantPoolOffsets = null;
+ super.reset();
+}
/**
* Answer the size of the receiver in bytes.
*
@@ -281,26 +410,4 @@ public String toString() {
.toString();
}
-public int compareTo(Object o) {
- if (!(o instanceof FieldInfo)) {
- throw new ClassCastException();
- }
- return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
-}
-/**
- * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
- * will be therefore fully initialized and we can get rid of the bytes.
- */
-void initialize() {
- getModifiers();
- getName();
- getConstant();
- getTypeName();
- reset();
-}
-protected void reset() {
- this.constantPoolOffsets = null;
- super.reset();
-}
-
}
diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index c9255be..7a27b96 100644
--- a/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/src/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -10,20 +10,25 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.classfmt;
+import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
public class MethodInfo extends ClassFileStruct implements IBinaryMethod, AttributeNamesConstants, Comparable {
- private char[][] exceptionNames;
- private int[] constantPoolOffsets;
- private boolean isDeprecated;
- private boolean isSynthetic;
+ static private final char[][] noException = CharOperation.NO_CHAR_CHAR;
private int accessFlags;
+ private int attributeBytes;
+ private int[] constantPoolOffsets;
+ private char[] descriptor;
+ private char[][] exceptionNames;
private char[] name;
private char[] signature;
- private int attributeBytes;
- static private final char[][] noException = CharOperation.NO_CHAR_CHAR;
+ private int signatureUtf8Offset;
+ private long tagBits;
+
/**
* @param classFileBytes byte[]
* @param offsets int[]
@@ -35,11 +40,108 @@ public MethodInfo (byte classFileBytes[], int offsets[], int offset) {
accessFlags = -1;
int attributesCount = u2At(6);
int readOffset = 8;
+ this.signatureUtf8Offset = -1;
for (int i = 0; i < attributesCount; i++) {
+ // check the name of each attribute
+ int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+ char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ if (attributeName.length > 0) {
+ switch(attributeName[0]) {
+ case 'S' :
+ if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) {
+ this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+ }
+ break;
+ case 'R' :
+ if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) {
+ decodeStandardAnnotations(readOffset);
+ }
+ }
+ }
readOffset += (6 + u4At(readOffset + 2));
}
attributeBytes = readOffset;
}
+public int compareTo(Object o) {
+ if (!(o instanceof MethodInfo)) {
+ throw new ClassCastException();
+ }
+
+ MethodInfo otherMethod = (MethodInfo) o;
+ int result = new String(this.getSelector()).compareTo(new String(otherMethod.getSelector()));
+ if (result != 0) return result;
+ return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor()));
+}
+private int decodeAnnotation(int offset) {
+ int readOffset = offset;
+ int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset;
+ char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ typeName = Signature.toCharArray(typeName);
+ CharOperation.replace(typeName, '/', '.');
+ char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName);
+ int numberOfPairs = u2At(offset + 2);
+ readOffset += 4;
+ if (qualifiedTypeName.length == 3) {
+ char[] lastPart = qualifiedTypeName[2];
+ if (lastPart[0] == 'D') {
+ if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) {
+ this.tagBits |= TagBits.AnnotationDeprecated;
+ return readOffset;
+ }
+ }
+ }
+ for (int i = 0; i < numberOfPairs; i++) {
+ readOffset += 2;
+ readOffset = decodeElementValue(readOffset);
+ }
+ return readOffset;
+}
+private int decodeElementValue(int offset) {
+ int readOffset = offset;
+ int tag = u1At(readOffset);
+ readOffset++;
+ switch(tag) {
+ case 'B' :
+ case 'C' :
+ case 'D' :
+ case 'F' :
+ case 'I' :
+ case 'J' :
+ case 'S' :
+ case 'Z' :
+ case 's' :
+ readOffset += 2;
+ break;
+ case 'e' :
+ readOffset += 4;
+ break;
+ case 'c' :
+ readOffset += 2;
+ break;
+ case '@' :
+ readOffset += decodeAnnotation(readOffset);
+ break;
+ case '[' :
+ int numberOfValues = u2At(readOffset);
+ readOffset += 2;
+ for (int i = 0; i < numberOfValues; i++) {
+ readOffset = decodeElementValue(readOffset);
+ }
+ break;
+ }
+ return readOffset;
+}
+/**
+ * @param offset the offset is located at the beginning of the runtime visible
+ * annotation attribute.
+ */
+private void decodeStandardAnnotations(int offset) {
+ int numberOfAnnotations = u2At(offset + 6);
+ int readOffset = offset + 8;
+ for (int i = 0; i < numberOfAnnotations; i++) {
+ readOffset = decodeAnnotation(readOffset);
+ }
+}
/**
* @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames()
*/
@@ -60,6 +162,16 @@ public char[][] getExceptionTypeNames() {
}
return exceptionNames;
}
+public char[] getGenericSignature() {
+ if (this.signatureUtf8Offset != -1) {
+ if (this.signature == null) {
+ // decode the signature
+ this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1));
+ }
+ return this.signature;
+ }
+ return null;
+}
/**
* Answer the receiver's method descriptor which describes the parameter &
* return types as specified in section 4.3.3 of the Java 2 VM spec.
@@ -70,12 +182,12 @@ public char[][] getExceptionTypeNames() {
* @return char[]
*/
public char[] getMethodDescriptor() {
- if (signature == null) {
+ if (descriptor == null) {
// read the name
int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
- signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
}
- return signature;
+ return descriptor;
}
/**
* Answer an int whose bits are set according the access constants
@@ -84,18 +196,12 @@ public char[] getMethodDescriptor() {
* @return int
*/
public int getModifiers() {
- if (accessFlags == -1) {
+ if (this.accessFlags == -1) {
// compute the accessflag. Don't forget the deprecated attribute
- accessFlags = u2At(0);
- readDeprecatedAndSyntheticAttributes();
- if (isDeprecated) {
- accessFlags |= AccDeprecated;
- }
- if (isSynthetic) {
- accessFlags |= AccSynthetic;
- }
+ this.accessFlags = u2At(0);
+ readModifierRelatedAttributes();
}
- return accessFlags;
+ return this.accessFlags;
}
/**
* Answer the name of the method.
@@ -111,6 +217,21 @@ public char[] getSelector() {
}
return name;
}
+public long getTagBits() {
+ return this.tagBits;
+}
+/**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+ getModifiers();
+ getSelector();
+ getMethodDescriptor();
+ getExceptionTypeNames();
+ getGenericSignature();
+ reset();
+}
/**
* Answer true if the method is a class initializer, false otherwise.
* @return boolean
@@ -134,20 +255,6 @@ public boolean isConstructor() {
public boolean isSynthetic() {
return (getModifiers() & AccSynthetic) != 0;
}
-private void readDeprecatedAndSyntheticAttributes() {
- int attributesCount = u2At(6);
- int readOffset = 8;
- 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, DeprecatedName)) {
- isDeprecated = true;
- } else if (CharOperation.equals(attributeName, SyntheticName)) {
- isSynthetic = true;
- }
- readOffset += (6 + u4At(readOffset + 2));
- }
-}
private void readExceptionAttributes() {
int attributesCount = u2At(6);
int readOffset = 8;
@@ -180,6 +287,36 @@ private void readExceptionAttributes() {
exceptionNames = noException;
}
}
+private void readModifierRelatedAttributes() {
+ int attributesCount = u2At(6);
+ int readOffset = 8;
+ for (int i = 0; i < attributesCount; i++) {
+ int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset;
+ char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+ // test added for obfuscated .class file. See 79772
+ if (attributeName.length != 0) {
+ switch(attributeName[0]) {
+ case 'D' :
+ if (CharOperation.equals(attributeName, DeprecatedName))
+ this.accessFlags |= AccDeprecated;
+ break;
+ case 'S' :
+ if (CharOperation.equals(attributeName, SyntheticName))
+ this.accessFlags |= AccSynthetic;
+ break;
+ case 'A' :
+ if (CharOperation.equals(attributeName, AnnotationDefaultName))
+ this.accessFlags |= AccAnnotationDefault;
+ break;
+ }
+ }
+ readOffset += (6 + u4At(readOffset + 2));
+ }
+}
+protected void reset() {
+ this.constantPoolOffsets = null;
+ super.reset();
+}
/**
* Answer the size of the receiver in bytes.
*
@@ -190,6 +327,9 @@ public int sizeInBytes() {
}
public String toString() {
int modifiers = getModifiers();
+ char[] desc = getGenericSignature();
+ if (desc == null)
+ desc = getMethodDescriptor();
StringBuffer buffer = new StringBuffer(this.getClass().getName());
return buffer
.append("{") //$NON-NLS-1$
@@ -201,36 +341,10 @@ public String toString() {
+ ((modifiers & 0x0008) == 0x000008 ? "static " : "") //$NON-NLS-1$ //$NON-NLS-2$
+ ((modifiers & 0x0010) == 0x0010 ? "final " : "") //$NON-NLS-1$ //$NON-NLS-2$
+ ((modifiers & 0x0040) == 0x0040 ? "volatile " : "") //$NON-NLS-1$ //$NON-NLS-2$
- + ((modifiers & 0x0080) == 0x0080 ? "transient " : "")) //$NON-NLS-1$ //$NON-NLS-2$
+ + ((modifiers & 0x0080) == 0x0080 ? "varargs " : "")) //$NON-NLS-1$ //$NON-NLS-2$
.append(getSelector())
- .append(getMethodDescriptor())
+ .append(desc)
.append("}") //$NON-NLS-1$
.toString();
}
-public int compareTo(Object o) {
- if (!(o instanceof MethodInfo)) {
- throw new ClassCastException();
- }
-
- MethodInfo otherMethod = (MethodInfo) o;
- int result = new String(this.getSelector()).compareTo(new String(otherMethod.getSelector()));
- if (result != 0) return result;
- return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor()));
-}
-
-/**
- * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
- * will be therefore fully initialized and we can get rid of the bytes.
- */
-void initialize() {
- getModifiers();
- getSelector();
- getMethodDescriptor();
- getExceptionTypeNames();
- reset();
-}
-protected void reset() {
- this.constantPoolOffsets = null;
- super.reset();
-}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java b/src/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
index 577b9bd..a49ff00 100644
--- a/src/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
+++ b/src/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
@@ -11,13 +11,21 @@
package org.eclipse.jdt.internal.compiler.codegen;
public interface AttributeNamesConstants {
- final char[] SyntheticName = new char[] {'S', 'y', 'n', 't', 'h', 'e', 't', 'i', 'c'};
- final char[] ConstantValueName = new char[] {'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'V', 'a', 'l', 'u', 'e'};
- final char[] LineNumberTableName = new char[] {'L', 'i', 'n', 'e', 'N', 'u', 'm', 'b', 'e', 'r', 'T', 'a', 'b', 'l', 'e'};
- final char[] LocalVariableTableName = new char[] {'L', 'o', 'c', 'a', 'l', 'V', 'a', 'r', 'i', 'a', 'b', 'l', 'e', 'T', 'a', 'b', 'l', 'e'};
- final char[] InnerClassName = new char[] {'I', 'n', 'n', 'e', 'r', 'C', 'l', 'a', 's', 's', 'e', 's'};
- final char[] CodeName = new char[] {'C', 'o', 'd', 'e'};
- final char[] ExceptionsName = new char[] {'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', 's'};
- final char[] SourceName = new char[] {'S', 'o', 'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e'};
- final char[] DeprecatedName = new char[] {'D', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd'};
+ final char[] SyntheticName = "Synthetic".toCharArray(); //$NON-NLS-1$
+ final char[] ConstantValueName = "ConstantValue".toCharArray(); //$NON-NLS-1$
+ final char[] LineNumberTableName = "LineNumberTable".toCharArray(); //$NON-NLS-1$
+ final char[] LocalVariableTableName = "LocalVariableTable".toCharArray(); //$NON-NLS-1$
+ final char[] InnerClassName = "InnerClasses".toCharArray(); //$NON-NLS-1$
+ final char[] CodeName = "Code".toCharArray(); //$NON-NLS-1$
+ final char[] ExceptionsName = "Exceptions".toCharArray(); //$NON-NLS-1$
+ final char[] SourceName = "SourceFile".toCharArray(); //$NON-NLS-1$
+ final char[] DeprecatedName = "Deprecated".toCharArray(); //$NON-NLS-1$
+ final char[] SignatureName = "Signature".toCharArray(); //$NON-NLS-1$
+ final char[] LocalVariableTypeTableName = "LocalVariableTypeTable".toCharArray(); //$NON-NLS-1$
+ final char[] EnclosingMethodName = "EnclosingMethod".toCharArray(); //$NON-NLS-1$
+ final char[] AnnotationDefaultName = "AnnotationDefault".toCharArray(); //$NON-NLS-1$
+ final char[] RuntimeInvisibleAnnotationsName = "RuntimeInvisibleAnnotations".toCharArray(); //$NON-NLS-1$
+ final char[] RuntimeVisibleAnnotationsName = "RuntimeVisibleAnnotations".toCharArray(); //$NON-NLS-1$
+ final char[] RuntimeInvisibleParameterAnnotationsName = "RuntimeInvisibleParameterAnnotations".toCharArray(); //$NON-NLS-1$
+ final char[] RuntimeVisibleParameterAnnotationsName = "RuntimeVisibleParameterAnnotations".toCharArray(); //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 4d7a6ef..343c4e6 100644
--- a/src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/src/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -49,7 +49,9 @@ public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
public AbstractMethodDeclaration methodDeclaration;
public ExceptionLabel[] exceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
- public int exceptionHandlersNumber;
+ public int exceptionHandlersIndex;
+ public int exceptionHandlersCounter;
+
public static FieldBinding[] ImplicitThis = new FieldBinding[] {};
public boolean generateLineNumberAttributes;
public boolean generateLocalVariableTableAttributes;
@@ -65,11 +67,15 @@ public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, Bas
public boolean wideMode = false;
public static final CompilationResult RESTART_IN_WIDE_MODE = new CompilationResult((char[])null, 0, 0, 0);
-public CodeStream(ClassFile classFile) {
- generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
- generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
- if (generateLineNumberAttributes) {
- lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
+ // target level to manage different code generation between different target levels
+ private long targetLevel;
+
+public CodeStream(ClassFile classFile, long targetLevel) {
+ this.targetLevel = targetLevel;
+ this.generateLineNumberAttributes = (classFile.produceDebugAttributes & CompilerOptions.Lines) != 0;
+ this.generateLocalVariableTableAttributes = (classFile.produceDebugAttributes & CompilerOptions.Vars) != 0;
+ if (this.generateLineNumberAttributes) {
+ this.lineSeparatorPositions = classFile.referenceBinding.scope.referenceCompilationUnit().compilationResult.lineSeparatorPositions;
}
}
final public void aaload() {
@@ -248,7 +254,7 @@ public final void anewarray(TypeBinding typeBinding) {
}
position++;
bCodeStream[classFileOffset++] = OPC_anewarray;
- writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
}
final public void areturn() {
if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$
@@ -482,14 +488,14 @@ final public void castore() {
bCodeStream[classFileOffset++] = OPC_castore;
}
public final void checkcast(TypeBinding typeBinding) {
- if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$
+ if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding.debugName()); //$NON-NLS-1$
countLabels = 0;
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
}
position++;
bCodeStream[classFileOffset++] = OPC_checkcast;
- writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
}
final public void d2f() {
if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$
@@ -1260,80 +1266,85 @@ public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBin
this.getTYPE(accessedType.id);
return;
}
- endLabel = new Label(this);
-
- if (syntheticFieldBinding != null) { // non interface case
- this.getstatic(syntheticFieldBinding);
- this.dup();
- this.ifnonnull(endLabel);
- this.pop();
- }
-
- /* Macro for building a class descriptor object... using or not a field cache to store it into...
- this sequence is responsible for building the actual class descriptor.
-
- If the fieldCache is set, then it is supposed to be the body of a synthetic access method
- factoring the actual descriptor creation out of the invocation site (saving space).
- If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
- we have no way to get a hand on the field cache to do better. */
-
- // Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
-
- anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
- this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
- this.invokeClassForName();
-
- /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
- if (accessedType == BaseTypes.NullBinding) {
- this.ldc("java.lang.Object"); //$NON-NLS-1$
- } else if (accessedType.isArrayType()) {
- this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+ if (this.targetLevel >= ClassFileConstants.JDK1_5) {
+ // generation using the new ldc_w bytecode
+ this.ldc(accessedType);
} else {
- // we make it an array type (to avoid class initialization)
- this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
- }
- this.invokeClassForName();
- if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
- this.invokeJavaLangClassGetComponentType();
- }
- */
- /* We need to protect the runtime code from binary inconsistencies
- in case the accessedType is missing, the ClassNotFoundException has to be converted
- into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
- anyExceptionHandler.placeEnd();
+ endLabel = new Label(this);
+ if (syntheticFieldBinding != null) { // non interface case
+ this.getstatic(syntheticFieldBinding);
+ this.dup();
+ this.ifnonnull(endLabel);
+ this.pop();
+ }
- if (syntheticFieldBinding != null) { // non interface case
- this.dup();
- this.putstatic(syntheticFieldBinding);
+ /* Macro for building a class descriptor object... using or not a field cache to store it into...
+ this sequence is responsible for building the actual class descriptor.
+
+ If the fieldCache is set, then it is supposed to be the body of a synthetic access method
+ factoring the actual descriptor creation out of the invocation site (saving space).
+ If the fieldCache is nil, then we are dumping the bytecode on the invocation site, since
+ we have no way to get a hand on the field cache to do better. */
+
+
+ // Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
+
+ anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
+ this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
+ this.invokeClassForName();
+
+ /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
+ if (accessedType == BaseTypes.NullBinding) {
+ this.ldc("java.lang.Object"); //$NON-NLS-1$
+ } else if (accessedType.isArrayType()) {
+ this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+ } else {
+ // we make it an array type (to avoid class initialization)
+ this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ this.invokeClassForName();
+ if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
+ this.invokeJavaLangClassGetComponentType();
+ }
+ */
+ /* We need to protect the runtime code from binary inconsistencies
+ in case the accessedType is missing, the ClassNotFoundException has to be converted
+ into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
+ anyExceptionHandler.placeEnd();
+
+ if (syntheticFieldBinding != null) { // non interface case
+ this.dup();
+ this.putstatic(syntheticFieldBinding);
+ }
+ this.goto_(endLabel);
+
+
+ // Generate the body of the exception handler
+ saveStackSize = stackDepth;
+ stackDepth = 1;
+ /* ClassNotFoundException on stack -- the class literal could be doing more things
+ on the stack, which means that the stack may not be empty at this point in the
+ above code gen. So we save its state and restart it from 1. */
+
+ anyExceptionHandler.place();
+
+ // Transform the current exception, and repush and throw a
+ // NoClassDefFoundError(ClassNotFound.getMessage())
+
+ this.newNoClassDefFoundError();
+ this.dup_x1();
+ this.swap();
+
+ // Retrieve the message from the old exception
+ this.invokeThrowableGetMessage();
+
+ // Send the constructor taking a message string as an argument
+ this.invokeNoClassDefFoundErrorStringConstructor();
+ this.athrow();
+ stackDepth = saveStackSize;
+ endLabel.place();
}
- this.goto_(endLabel);
-
-
- // Generate the body of the exception handler
- saveStackSize = stackDepth;
- stackDepth = 1;
- /* ClassNotFoundException on stack -- the class literal could be doing more things
- on the stack, which means that the stack may not be empty at this point in the
- above code gen. So we save its state and restart it from 1. */
-
- anyExceptionHandler.place();
-
- // Transform the current exception, and repush and throw a
- // NoClassDefFoundError(ClassNotFound.getMessage())
-
- this.newNoClassDefFoundError();
- this.dup_x1();
- this.swap();
-
- // Retrieve the message from the old exception
- this.invokeThrowableGetMessage();
-
- // Send the constructor taking a message string as an argument
- this.invokeNoClassDefFoundErrorStringConstructor();
- this.athrow();
- endLabel.place();
- stackDepth = saveStackSize;
}
/**
* This method generates the code attribute bytecode
@@ -1346,41 +1357,57 @@ final public void generateCodeAttributeForProblemMethod(String problemMessage) {
athrow();
}
public void generateConstant(Constant constant, int implicitConversionCode) {
- int targetTypeID = implicitConversionCode >> 4;
- switch (targetTypeID) {
- case T_boolean :
- generateInlinedValue(constant.booleanValue());
- break;
- case T_char :
- generateInlinedValue(constant.charValue());
- break;
- case T_byte :
- generateInlinedValue(constant.byteValue());
- break;
- case T_short :
- generateInlinedValue(constant.shortValue());
- break;
- case T_int :
- generateInlinedValue(constant.intValue());
- break;
- case T_long :
- generateInlinedValue(constant.longValue());
- break;
- case T_float :
- generateInlinedValue(constant.floatValue());
- break;
- case T_double :
- generateInlinedValue(constant.doubleValue());
- break;
- default : //String or Object
- ldc(constant.stringValue());
+ int targetTypeID = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+ if (targetTypeID != 0) {
+ switch (targetTypeID) {
+ case T_boolean :
+ generateInlinedValue(constant.booleanValue());
+ break;
+ case T_char :
+ generateInlinedValue(constant.charValue());
+ break;
+ case T_byte :
+ generateInlinedValue(constant.byteValue());
+ break;
+ case T_short :
+ generateInlinedValue(constant.shortValue());
+ break;
+ case T_int :
+ generateInlinedValue(constant.intValue());
+ break;
+ case T_long :
+ generateInlinedValue(constant.longValue());
+ break;
+ case T_float :
+ generateInlinedValue(constant.floatValue());
+ break;
+ case T_double :
+ generateInlinedValue(constant.doubleValue());
+ break;
+ case T_JavaLangString :
+ ldc(constant.stringValue());
+ }
+ } else {
+ ldc(constant.stringValue());
+ }
+ if ((implicitConversionCode & BOXING) != 0) {
+ // need boxing
+ generateBoxingConversion(targetTypeID);
}
}
+
/**
+ * Generates the sequence of instructions which will perform the conversion of the expression
+ * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
* @param implicitConversionCode int
*/
public void generateImplicitConversion(int implicitConversionCode) {
- switch (implicitConversionCode) {
+ if ((implicitConversionCode & UNBOXING) != 0) {
+ final int typeId = implicitConversionCode & COMPILE_TYPE_MASK;
+ generateUnboxingConversion(typeId);
+ // unboxing can further involve base type conversions
+ }
+ switch (implicitConversionCode & IMPLICIT_CONVERSION_MASK) {
case Float2Char :
this.f2i();
this.i2c();
@@ -1477,6 +1504,11 @@ public void generateImplicitConversion(int implicitConversionCode) {
case Float2Long :
this.f2l();
}
+ if ((implicitConversionCode & BOXING) != 0) {
+ // need to unbox/box the constant
+ final int typeId = (implicitConversionCode & IMPLICIT_CONVERSION_MASK) >> 4;
+ generateBoxingConversion(typeId);
+ }
}
public void generateInlinedValue(byte inlinedValue) {
switch (inlinedValue) {
@@ -1699,27 +1731,27 @@ public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite
* @param oper1 the first expression
* @param oper2 the second expression
*/
-public void generateStringAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
+public void generateStringConcatenationAppend(BlockScope blockScope, Expression oper1, Expression oper2) {
int pc;
if (oper1 == null) {
/* Operand is already on the stack, and maybe nil:
note type1 is always to java.lang.String here.*/
- this.newStringBuffer();
+ this.newStringContatenation();
this.dup_x1();
this.swap();
// If argument is reference type, need to transform it
// into a string (handles null case)
- this.invokeStringValueOf(T_Object);
- this.invokeStringBufferStringConstructor();
+ this.invokeStringValueOf(T_JavaLangObject);
+ this.invokeStringConcatenationStringConstructor();
} else {
pc = position;
- oper1.generateOptimizedStringBufferCreation(blockScope, this, oper1.implicitConversion & 0xF);
+ oper1.generateOptimizedStringConcatenationCreation(blockScope, this, oper1.implicitConversion & COMPILE_TYPE_MASK);
this.recordPositionsFrom(pc, oper1.sourceStart);
}
pc = position;
- oper2.generateOptimizedStringBuffer(blockScope, this, oper2.implicitConversion & 0xF);
+ oper2.generateOptimizedStringConcatenation(blockScope, this, oper2.implicitConversion & COMPILE_TYPE_MASK);
this.recordPositionsFrom(pc, oper2.sourceStart);
- this.invokeStringBufferToString();
+ this.invokeStringConcatenationToString();
}
/**
* Code responsible to generate the suitable code to supply values for the synthetic enclosing
@@ -1795,7 +1827,7 @@ public void generateSyntheticOuterArgumentValues(BlockScope currentScope, Refere
/**
* @param accessBinding the access method binding to generate
*/
-public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) {
initializeMaxLocals(accessBinding);
@@ -1804,8 +1836,14 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
int length = parameters.length;
int resolvedPosition = 1;
this.aload_0();
- if (constructorBinding.declaringClass.isNestedType()) {
- NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+ // special name&ordinal argument generation for enum constructors
+ TypeBinding declaringClass = constructorBinding.declaringClass;
+ if (declaringClass.erasure().id == T_JavaLangEnum || declaringClass.isEnum()) {
+ this.aload_1(); // pass along name param as name arg
+ this.iload_2(); // pass along ordinal param as ordinal arg
+ }
+ if (declaringClass.isNestedType()) {
+ NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances();
for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
TypeBinding type;
@@ -1824,8 +1862,8 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
resolvedPosition++;
}
- if (constructorBinding.declaringClass.isNestedType()) {
- NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+ if (declaringClass.isNestedType()) {
+ NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
TypeBinding type;
@@ -1839,7 +1877,82 @@ public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBindi
this.invokespecial(constructorBinding);
this.return_();
}
-public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding accessBinding) {
+//static X[] values() {
+// X[] values;
+// int length;
+// X[] result;
+// System.arraycopy(values = $VALUES, 0, result = new X[length= values.length], 0, length)
+// return result;
+//}
+public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
+ ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+ FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+ initializeMaxLocals(methodBinding);
+ TypeBinding enumArray = methodBinding.returnType;
+
+ this.getstatic(enumValuesSyntheticfield);
+ this.dup();
+ this.astore_0();
+ this.iconst_0();
+ this.aload_0();
+ this.arraylength();
+ this.dup();
+ this.istore_1();
+ this.newArray((ArrayBinding) enumArray);
+ this.dup();
+ this.astore_2();
+ this.iconst_0();
+ this.iload_1();
+ this.invokeSystemArraycopy();
+ this.aload_2();
+ this.areturn();
+}
+//static X valueOf(String name) {
+// X[] values;
+// for (int i = (values = $VALUES).length; --i >= 0;) {
+// X value;
+// if (name.equals(value = values[i].name())) return value;
+// }
+// throw new IllegalArgumentException(name);
+//}
+public void generateSyntheticBodyForEnumValueOf(SyntheticMethodBinding methodBinding) {
+ ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
+ FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
+ initializeMaxLocals(methodBinding);
+ Label loopCond = new Label(this);
+ Label loopStart = new Label(this);
+ Label wrongConstant = new Label(this);
+
+ this.getstatic(enumValuesSyntheticfield);
+ this.dup();
+ this.astore_1();
+ this.arraylength();
+ this.istore_2();
+ this.goto_(loopCond);
+ loopStart.place();
+ this.aload_0();
+ this.aload_1();
+ this.iload_2();
+ this.aaload();
+ this.dup();
+ this.astore_3();
+ this.invokeJavaLangEnumname(this.classFile.referenceBinding);
+ this.invokeStringEquals();
+ this.ifeq(wrongConstant);
+ this.aload_3();
+ this.areturn();
+ wrongConstant.place();
+ loopCond.place();
+ this.iinc(2, -1);
+ this.iload_2();
+ this.ifge(loopStart);
+ this.newJavaLangIllegalArgumentException();
+ this.dup();
+ this.aload_0();
+ this.invokeJavaLangIllegalArgumentExceptionStringConstructor();
+ this.athrow();
+}
+public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
initializeMaxLocals(accessBinding);
FieldBinding fieldBinding = accessBinding.targetReadField;
TypeBinding type;
@@ -1866,7 +1979,7 @@ public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding
} else
this.areturn();
}
-public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForFieldWriteAccess(SyntheticMethodBinding accessBinding) {
initializeMaxLocals(accessBinding);
FieldBinding fieldBinding = accessBinding.targetWriteField;
if (fieldBinding.isStatic()) {
@@ -1879,12 +1992,15 @@ public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBindin
}
this.return_();
}
-public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding accessBinding) {
+public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessBinding) {
initializeMaxLocals(accessBinding);
MethodBinding methodBinding = accessBinding.targetMethod;
TypeBinding[] parameters = methodBinding.parameters;
int length = parameters.length;
+ TypeBinding[] arguments = accessBinding.kind == SyntheticMethodBinding.BridgeMethod
+ ? accessBinding.parameters
+ : null;
int resolvedPosition;
if (methodBinding.isStatic())
resolvedPosition = 0;
@@ -1893,8 +2009,16 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
resolvedPosition = 1;
}
for (int i = 0; i < length; i++) {
- load(parameters[i], resolvedPosition);
- if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding))
+ TypeBinding parameter = parameters[i];
+ if (arguments != null) { // for bridge methods
+ TypeBinding argument = arguments[i];
+ load(argument, resolvedPosition);
+ if (argument != parameter)
+ checkcast(parameter);
+ } else {
+ load(parameter, resolvedPosition);
+ }
+ if ((parameter == DoubleBinding) || (parameter == LongBinding))
resolvedPosition += 2;
else
resolvedPosition++;
@@ -1906,10 +2030,10 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
if (methodBinding.isConstructor()
|| methodBinding.isPrivate()
// qualified super "X.super.foo()" targets methods from superclass
- || accessBinding.accessType == SyntheticAccessMethodBinding.SuperMethodAccess){
+ || accessBinding.kind == SyntheticMethodBinding.SuperMethodAccess){
this.invokespecial(methodBinding);
} else {
- if (methodBinding.declaringClass.isInterface()){
+ if ((methodBinding.declaringClass.modifiers & AccInterface) != 0) { // interface or annotation type
this.invokeinterface(methodBinding);
} else {
this.invokevirtual(methodBinding);
@@ -1936,6 +2060,172 @@ public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding ac
else
this.areturn();
}
+public void generateBoxingConversion(int unboxedTypeID) {
+ switch (unboxedTypeID) {
+ case T_byte :
+ // invokestatic: Byte.valueOf(byte)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangByteConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.byteByteSignature); //$NON-NLS-1$
+ break;
+ case T_short :
+ // invokestatic: Short.valueOf(short)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangShortConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.shortShortSignature); //$NON-NLS-1$
+ break;
+ case T_char :
+ // invokestatic: Character.valueOf(char)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangCharacterConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.charCharacterSignature); //$NON-NLS-1$
+ break;
+ case T_int :
+ // invokestatic: Integer.valueOf(int)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangIntegerConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.IntIntegerSignature); //$NON-NLS-1$
+ break;
+ case T_long :
+ // invokestatic: Long.valueOf(long)
+ this.invoke(
+ OPC_invokestatic,
+ 2, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangLongConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.longLongSignature); //$NON-NLS-1$
+ break;
+ case T_float :
+ // invokestatic: Float.valueOf(float)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangFloatConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.floatFloatSignature); //$NON-NLS-1$
+ break;
+ case T_double :
+ // invokestatic: Double.valueOf(double)
+ this.invoke(
+ OPC_invokestatic,
+ 2, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangDoubleConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.doubleDoubleSignature); //$NON-NLS-1$
+ break;
+ case T_boolean :
+ // invokestatic: Boolean.valueOf(boolean)
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangBooleanConstantPoolName,
+ ConstantPool.ValueOf,
+ ConstantPool.booleanBooleanSignature); //$NON-NLS-1$
+ }
+}
+public void generateUnboxingConversion(int unboxedTypeID) {
+ switch (unboxedTypeID) {
+ case T_byte :
+ // invokevirtual: byteValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangByteConstantPoolName,
+ ConstantPool.BYTEVALUE_BYTE_METHOD_NAME,
+ ConstantPool.BYTEVALUE_BYTE_METHOD_SIGNATURE);
+ break;
+ case T_short :
+ // invokevirtual: shortValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangShortConstantPoolName,
+ ConstantPool.SHORTVALUE_SHORT_METHOD_NAME,
+ ConstantPool.SHORTVALUE_SHORT_METHOD_SIGNATURE);
+ break;
+ case T_char :
+ // invokevirtual: charValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangCharacterConstantPoolName,
+ ConstantPool.CHARVALUE_CHARACTER_METHOD_NAME,
+ ConstantPool.CHARVALUE_CHARACTER_METHOD_SIGNATURE);
+ break;
+ case T_int :
+ // invokevirtual: intValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangIntegerConstantPoolName,
+ ConstantPool.INTVALUE_INTEGER_METHOD_NAME,
+ ConstantPool.INTVALUE_INTEGER_METHOD_SIGNATURE);
+ break;
+ case T_long :
+ // invokevirtual: longValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 2, // return type size
+ ConstantPool.JavaLangLongConstantPoolName,
+ ConstantPool.LONGVALUE_LONG_METHOD_NAME,
+ ConstantPool.LONGVALUE_LONG_METHOD_SIGNATURE);
+ break;
+ case T_float :
+ // invokevirtual: floatValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangFloatConstantPoolName,
+ ConstantPool.FLOATVALUE_FLOAT_METHOD_NAME,
+ ConstantPool.FLOATVALUE_FLOAT_METHOD_SIGNATURE);
+ break;
+ case T_double :
+ // invokevirtual: doubleValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 2, // return type size
+ ConstantPool.JavaLangDoubleConstantPoolName,
+ ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_NAME,
+ ConstantPool.DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
+ break;
+ case T_boolean :
+ // invokevirtual: booleanValue()
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangBooleanConstantPoolName,
+ ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_NAME,
+ ConstantPool.BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
+ }
+}
final public byte[] getContents() {
byte[] contents;
System.arraycopy(bCodeStream, 0, contents = new byte[position], 0, position);
@@ -1943,88 +2233,161 @@ final public byte[] getContents() {
}
final public void getfield(FieldBinding fieldBinding) {
if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$
- countLabels = 0;
+ int returnTypeSize = 1;
if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
- if (++stackDepth > stackMax)
- stackMax = stackDepth;
+ returnTypeSize = 2;
+ }
+ generateFieldAccess(
+ OPC_getfield,
+ returnTypeSize,
+ fieldBinding.declaringClass.constantPoolName(),
+ fieldBinding.name,
+ fieldBinding.type.signature());
+}
+private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) {
+ countLabels = 0;
+ switch(opcode) {
+ case OPC_getfield :
+ if (returnTypeSize == 2) {
+ stackDepth++;
+ }
+ break;
+ case OPC_getstatic :
+ if (returnTypeSize == 2) {
+ stackDepth += 2;
+ } else {
+ stackDepth++;
+ }
+ break;
+ case OPC_putfield :
+ if (returnTypeSize == 2) {
+ stackDepth -= 3;
+ } else {
+ stackDepth -= 2;
+ }
+ break;
+ case OPC_putstatic :
+ if (returnTypeSize == 2) {
+ stackDepth -= 2;
+ } else {
+ stackDepth--;
+ }
+ }
+ if (stackDepth > stackMax) {
+ stackMax = stackDepth;
}
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
}
position++;
- bCodeStream[classFileOffset++] = OPC_getfield;
- writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+ bCodeStream[classFileOffset++] = opcode;
+ writeUnsignedShort(constantPool.literalIndexForField(declaringClass, name, signature));
}
final public void getstatic(FieldBinding fieldBinding) {
if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$
- countLabels = 0;
- if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
- stackDepth += 2;
- else
- stackDepth += 1;
- if (stackDepth > stackMax)
- stackMax = stackDepth;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ int returnTypeSize = 1;
+ if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+ returnTypeSize = 2;
}
- position++;
- bCodeStream[classFileOffset++] = OPC_getstatic;
- writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+ generateFieldAccess(
+ OPC_getstatic,
+ returnTypeSize,
+ fieldBinding.declaringClass.constantPoolName(),
+ fieldBinding.name,
+ fieldBinding.type.signature());
}
public void getTYPE(int baseTypeID) {
countLabels = 0;
- if (++stackDepth > stackMax)
- stackMax = stackDepth;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_getstatic;
switch (baseTypeID) {
case T_byte :
// getstatic: java.lang.Byte.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Byte.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangByteConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_short :
// getstatic: java.lang.Short.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Short.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangShortConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_char :
// getstatic: java.lang.Character.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Character.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangCharacterConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_int :
// getstatic: java.lang.Integer.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Integer.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangIntegerConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_long :
// getstatic: java.lang.Long.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Long.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangLongConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_float :
// getstatic: java.lang.Float.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Float.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangFloatConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_double :
// getstatic: java.lang.Double.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Double.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangDoubleConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_boolean :
// getstatic: java.lang.Boolean.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Boolean.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangBooleanConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
case T_void :
// getstatic: java.lang.Void.TYPE
if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Void.TYPE"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE());
+ generateFieldAccess(
+ OPC_getstatic,
+ 1,
+ ConstantPool.JavaLangVoidConstantPoolName,
+ ConstantPool.TYPE,
+ ConstantPool.JavaLangClassSignature);
break;
}
}
@@ -2691,7 +3054,8 @@ public void init(ClassFile targetClassFile) {
noExceptionHandlers = new ExceptionLabel[length];
}
System.arraycopy(noExceptionHandlers, 0, exceptionHandlers, 0, length);
- exceptionHandlersNumber = 0;
+ exceptionHandlersIndex = 0;
+ exceptionHandlersCounter = 0;
length = labels.length;
if (noLabels.length < length) {
@@ -2710,41 +3074,50 @@ public void init(ClassFile targetClassFile) {
*/
public void initializeMaxLocals(MethodBinding methodBinding) {
- maxLocals = (methodBinding == null || methodBinding.isStatic()) ? 0 : 1;
+ if (methodBinding == null) {
+ this.maxLocals = 0;
+ return;
+ }
+
+ this.maxLocals = methodBinding.isStatic() ? 0 : 1;
+
+ // take into account enum constructor synthetic name+ordinal
+ if (methodBinding.isConstructor() && methodBinding.declaringClass.isEnum()) {
+ this.maxLocals += 2; // String and int (enum constant name+ordinal)
+ }
+
// take into account the synthetic parameters
- if (methodBinding != null) {
- if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
- ReferenceBinding enclosingInstanceTypes[];
- if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
- for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
- maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
- // LongBinding or DoubleBinding
- }
- }
- SyntheticArgumentBinding syntheticArguments[];
- if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
- for (int i = 0, max = syntheticArguments.length; i < max; i++) {
- TypeBinding argType;
- if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
- maxLocals += 2;
- } else {
- maxLocals++;
- }
- }
+ if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
+ ReferenceBinding enclosingInstanceTypes[];
+ if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) {
+ for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
+ this.maxLocals++; // an enclosingInstanceType can only be a reference binding. It cannot be
+ // LongBinding or DoubleBinding
}
}
- TypeBinding[] arguments;
- if ((arguments = methodBinding.parameters) != null) {
- for (int i = 0, max = arguments.length; i < max; i++) {
+ SyntheticArgumentBinding syntheticArguments[];
+ if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) {
+ for (int i = 0, max = syntheticArguments.length; i < max; i++) {
TypeBinding argType;
- if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
- maxLocals += 2;
+ if (((argType = syntheticArguments[i].type) == LongBinding) || (argType == DoubleBinding)) {
+ this.maxLocals += 2;
} else {
- maxLocals++;
+ this.maxLocals++;
}
}
}
}
+ TypeBinding[] arguments;
+ if ((arguments = methodBinding.parameters) != null) {
+ for (int i = 0, max = arguments.length; i < max; i++) {
+ TypeBinding argType;
+ if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
+ this.maxLocals += 2;
+ } else {
+ this.maxLocals++;
+ }
+ }
+ }
}
/**
* This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc.
@@ -2792,45 +3165,53 @@ final public void instance_of(TypeBinding typeBinding) {
}
position++;
bCodeStream[classFileOffset++] = OPC_instanceof;
- writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
}
public void invokeClassForName() {
// invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;
if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokestatic;
- writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName());
+ this.invoke(
+ OPC_invokestatic,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangClassConstantPoolName,
+ ConstantPool.ForName,
+ ConstantPool.ForNameSignature);
}
-
public void invokeJavaLangClassDesiredAssertionStatus() {
// invokevirtual: java.lang.Class.desiredAssertionStatus()Z;
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.desiredAssertionStatus()Z;"); //$NON-NLS-1$
- countLabels = 0;
- stackDepth--;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus());
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangClassConstantPoolName,
+ ConstantPool.DesiredAssertionStatus,
+ ConstantPool.DesiredAssertionStatusSignature);
}
public void invokeJavaLangClassGetComponentType() {
// invokevirtual: java.lang.Class.getComponentType()java.lang.Class;
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.getComponentType()java.lang.Class;"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetComponentType());
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangClassConstantPoolName,
+ ConstantPool.GetComponentType,
+ ConstantPool.GetComponentTypeSignature);
+}
+public void invokeEnumOrdinal(char[] enumTypeConstantPoolName) {
+ // invokevirtual: .ordinal()
+ if (DEBUG) System.out.println(position + "\t\tinvokevirtual: "+new String(enumTypeConstantPoolName)+".ordinal()"); //$NON-NLS-1$ //$NON-NLS-2$
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ enumTypeConstantPoolName,
+ ConstantPool.Ordinal,
+ ConstantPool.OrdinalSignature);
}
-
final public void invokeinterface(MethodBinding methodBinding) {
// initialized to 1 to take into account this immediately
if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$
@@ -2868,37 +3249,35 @@ final public void invokeinterface(MethodBinding methodBinding) {
public void invokeJavaLangErrorConstructor() {
// invokespecial: java.lang.Error(Ljava.lang.String;)V
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.Error(Ljava.lang.String;)V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- stackDepth -= 2;
- writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor());
+ this.invoke(
+ OPC_invokespecial,
+ 1, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangErrorConstantPoolName,
+ ConstantPool.Init,
+ ConstantPool.StringConstructorSignature);
}
public void invokeNoClassDefFoundErrorStringConstructor() {
// invokespecial: java.lang.NoClassDefFoundError.(Ljava.lang.String;)V
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.NoClassDefFoundError.(Ljava.lang.String;)V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- stackDepth -= 2;
- writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor());
+ this.invoke(
+ OPC_invokespecial,
+ 1, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName,
+ ConstantPool.Init,
+ ConstantPool.StringConstructorSignature);
}
public void invokeObjectGetClass() {
// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class;
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Object.getClass()Ljava.lang.Class;"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass());
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangObjectConstantPoolName,
+ ConstantPool.GetClass,
+ ConstantPool.GetClassSignature);
}
final public void invokespecial(MethodBinding methodBinding) {
@@ -2984,121 +3363,393 @@ final public void invokestatic(MethodBinding methodBinding) {
* The equivalent code performs a string conversion of the TOS
* @param typeID int
*/
-public void invokeStringBufferAppendForType(int typeID) {
- if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
- countLabels = 0;
- int usedTypeID;
- if (typeID == T_null)
- usedTypeID = T_String;
- else
- usedTypeID = typeID;
- // invokevirtual
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+public void invokeStringConcatenationAppendForType(int typeID) {
+ if (DEBUG) {
+ if (this.targetLevel >= JDK1_5) {
+ System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuilder.append(...)"); //$NON-NLS-1$
+ } else {
+ System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
+ }
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferAppend(typeID));
- if ((usedTypeID == T_long) || (usedTypeID == T_double))
- stackDepth -= 2;
- else
- stackDepth--;
+ int argCount = 1;
+ int returnType = 1;
+ char[] declarinClass = null;
+ char[] selector = ConstantPool.Append;
+ char[] signature = null;
+ switch (typeID) {
+ case T_int :
+ case T_byte :
+ case T_short :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendIntSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendIntSignature;
+ }
+ break;
+ case T_long :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendLongSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendLongSignature;
+ }
+ argCount = 2;
+ break;
+ case T_float :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendFloatSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendFloatSignature;
+ }
+ break;
+ case T_double :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendDoubleSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendDoubleSignature;
+ }
+ argCount = 2;
+ break;
+ case T_char :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendCharSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendCharSignature;
+ }
+ break;
+ case T_boolean :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendBooleanSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendBooleanSignature;
+ }
+ break;
+ case T_undefined :
+ case T_JavaLangObject :
+ case T_null :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendObjectSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendObjectSignature;
+ }
+ break;
+ case T_JavaLangString :
+ if (this.targetLevel >= JDK1_5) {
+ declarinClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ signature = ConstantPool.StringBuilderAppendStringSignature;
+ } else {
+ declarinClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ signature = ConstantPool.StringBufferAppendStringSignature;
+ }
+ break;
+ }
+ this.invoke(
+ OPC_invokevirtual,
+ argCount, // argCount
+ returnType, // return type size
+ declarinClass,
+ selector,
+ signature);
}
public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
// invokespecial: java.lang.AssertionError.(typeBindingID)V
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.(typeBindingID)V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ int argCount = 1;
+ char[] signature = null;
+ switch (typeBindingID) {
+ case T_int :
+ case T_byte :
+ case T_short :
+ signature = ConstantPool.IntConstrSignature;
+ break;
+ case T_long :
+ signature = ConstantPool.LongConstrSignature;
+ argCount = 2;
+ break;
+ case T_float :
+ signature = ConstantPool.FloatConstrSignature;
+ break;
+ case T_double :
+ signature = ConstantPool.DoubleConstrSignature;
+ argCount = 2;
+ break;
+ case T_char :
+ signature = ConstantPool.CharConstrSignature;
+ break;
+ case T_boolean :
+ signature = ConstantPool.BooleanConstrSignature;
+ break;
+ case T_JavaLangObject :
+ case T_JavaLangString :
+ case T_null :
+ signature = ConstantPool.ObjectConstrSignature;
+ break;
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID));
- stackDepth -= 2;
+ this.invoke(
+ OPC_invokespecial,
+ argCount, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangAssertionErrorConstantPoolName,
+ ConstantPool.Init,
+ signature);
}
public void invokeJavaLangAssertionErrorDefaultConstructor() {
// invokespecial: java.lang.AssertionError.()V
if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.()V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor());
- stackDepth --;
+ this.invoke(
+ OPC_invokespecial,
+ 0, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangAssertionErrorConstantPoolName,
+ ConstantPool.Init,
+ ConstantPool.DefaultConstructorSignature);
+}
+public void invokeJavaLangEnumname(TypeBinding typeBinding) {
+ // invokevirtual: java.lang.Enum.name()String
+ if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Enum.name()Ljava/lang/String;"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokevirtual,
+ 0,
+ 1,
+ typeBinding.constantPoolName(),
+ ConstantPool.Name,
+ ConstantPool.NameSignature);
+}
+public void invokeJavaLangIllegalArgumentExceptionStringConstructor() {
+ // invokespecial: java.lang.IllegalArgumentException.(String)V
+ if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.IllegalArgumentException.(java.lang.String)V"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokespecial,
+ 1, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName,
+ ConstantPool.Init,
+ ConstantPool.StringConstructorSignature);
}
-public void invokeStringBufferDefaultConstructor() {
+public void invokeJavaUtilIteratorHasNext() {
+ // invokeinterface java.util.Iterator.hasNext()Z
+ if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.hasNext()Z"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokeinterface,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaUtilIteratorConstantPoolName,
+ ConstantPool.HasNext,
+ ConstantPool.HasNextSignature);
+}
+public void invokeJavaUtilIteratorNext() {
+ // invokeinterface java.util.Iterator.next()java.lang.Object
+ if (DEBUG) System.out.println(position + "\t\tinvokeinterface: java.util.Iterator.next()java.lang.Object"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokeinterface,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaUtilIteratorConstantPoolName,
+ ConstantPool.Next,
+ ConstantPool.NextSignature);
+}
+public void invokeStringConcatenationDefaultConstructor() {
// invokespecial: java.lang.StringBuffer.()V
- if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.()V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ if (DEBUG) {
+ if (this.targetLevel >= JDK1_5) {
+ System.out.println(position + "\t\tinvokespecial: java.lang.StringBuilder.()V"); //$NON-NLS-1$
+ } else {
+ System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.()V"); //$NON-NLS-1$
+ }
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor());
- stackDepth--;
-}
-public void invokeStringBufferStringConstructor() {
- // invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V
- if (DEBUG) System.out.println(position + "\t\tjava.lang.StringBuffer.(Ljava.lang.String;)V"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ if (this.targetLevel >= JDK1_5) {
+ declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ }
+ this.invoke(
+ OPC_invokespecial,
+ 0, // argCount
+ 0, // return type size
+ declaringClass,
+ ConstantPool.Init,
+ ConstantPool.DefaultConstructorSignature);
+}
+public void invokeStringConcatenationStringConstructor() {
+ if (DEBUG) {
+ if (this.targetLevel >= JDK1_5) {
+ System.out.println(position + "\t\tjava.lang.StringBuilder.(Ljava.lang.String;)V"); //$NON-NLS-1$
+ } else {
+ System.out.println(position + "\t\tjava.lang.StringBuffer.(Ljava.lang.String;)V"); //$NON-NLS-1$
+ }
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokespecial;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor());
- stackDepth -= 2;
+ char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ if (this.targetLevel >= JDK1_5) {
+ declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ }
+ this.invoke(
+ OPC_invokespecial,
+ 1, // argCount
+ 0, // return type size
+ declaringClass,
+ ConstantPool.Init,
+ ConstantPool.StringConstructorSignature);
}
-public void invokeStringBufferToString() {
- // invokevirtual: StringBuffer.toString()Ljava.lang.String;
- if (DEBUG) System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+public void invokeStringConcatenationToString() {
+ if (DEBUG) {
+ if (this.targetLevel >= JDK1_5) {
+ System.out.println(position + "\t\tinvokevirtual: StringBuilder.toString()Ljava.lang.String;"); //$NON-NLS-1$
+ } else {
+ System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
+ }
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString());
+ char[] declaringClass = ConstantPool.JavaLangStringBufferConstantPoolName;
+ if (this.targetLevel >= JDK1_5) {
+ declaringClass = ConstantPool.JavaLangStringBuilderConstantPoolName;
+ }
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ declaringClass,
+ ConstantPool.ToString,
+ ConstantPool.ToStringSignature);
+}
+public void invokeStringEquals() {
+ // invokevirtual: java.lang.String.equals(java.lang.Object)
+ if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.equals(...)"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokevirtual,
+ 1, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangStringConstantPoolName,
+ ConstantPool.Equals,
+ ConstantPool.EqualsSignature);
}
public void invokeStringIntern() {
// invokevirtual: java.lang.String.intern()
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.intern()"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern());
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangStringConstantPoolName,
+ ConstantPool.Intern,
+ ConstantPool.InternSignature);
}
public void invokeStringValueOf(int typeID) {
// invokestatic: java.lang.String.valueOf(argumentType)
if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.String.valueOf(...)"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
- }
- position++;
- bCodeStream[classFileOffset++] = OPC_invokestatic;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
+ int argCount = 1;
+ char[] signature = null;
+ switch (typeID) {
+ case T_int :
+ case T_byte :
+ case T_short :
+ signature = ConstantPool.ValueOfIntSignature;
+ break;
+ case T_long :
+ signature = ConstantPool.ValueOfLongSignature;
+ argCount = 2;
+ break;
+ case T_float :
+ signature = ConstantPool.ValueOfFloatSignature;
+ break;
+ case T_double :
+ signature = ConstantPool.ValueOfDoubleSignature;
+ argCount = 2;
+ break;
+ case T_char :
+ signature = ConstantPool.ValueOfCharSignature;
+ break;
+ case T_boolean :
+ signature = ConstantPool.ValueOfBooleanSignature;
+ break;
+ case T_JavaLangObject :
+ case T_JavaLangString :
+ case T_null :
+ case T_undefined :
+ signature = ConstantPool.ValueOfObjectSignature;
+ break;
+ }
+ this.invoke(
+ OPC_invokestatic,
+ argCount, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangStringConstantPoolName,
+ ConstantPool.ValueOf,
+ signature);
+}
+public void invokeSystemArraycopy() {
+ // invokestatic #21
+ if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V"); //$NON-NLS-1$
+ this.invoke(
+ OPC_invokestatic,
+ 5, // argCount
+ 0, // return type size
+ ConstantPool.JavaLangSystemConstantPoolName,
+ ConstantPool.ArrayCopy,
+ ConstantPool.ArrayCopySignature);
}
public void invokeThrowableGetMessage() {
// invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;
if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;"); //$NON-NLS-1$
- countLabels = 0;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ this.invoke(
+ OPC_invokevirtual,
+ 0, // argCount
+ 1, // return type size
+ ConstantPool.JavaLangThrowableConstantPoolName,
+ ConstantPool.GetMessage,
+ ConstantPool.GetMessageSignature);
+}
+final public void invoke(int opcode, int argsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
+ countLabels = 0;
+ int argCount = argsSize;
+ switch(opcode) {
+ case OPC_invokeinterface :
+ if (classFileOffset + 4 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position +=3;
+ bCodeStream[classFileOffset++] = OPC_invokeinterface;
+ writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
+ argCount++;
+ bCodeStream[classFileOffset++] = (byte) argCount;
+ bCodeStream[classFileOffset++] = 0;
+ break;
+ case OPC_invokevirtual :
+ case OPC_invokespecial :
+ if (classFileOffset + 2 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position++;
+ bCodeStream[classFileOffset++] = (byte) opcode;
+ writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
+ argCount++;
+ break;
+ case OPC_invokestatic :
+ if (classFileOffset + 2 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokestatic;
+ writeUnsignedShort(constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
+ }
+ stackDepth += returnTypeSize - argCount;
+ if (stackDepth > stackMax) {
+ stackMax = stackDepth;
}
- position++;
- bCodeStream[classFileOffset++] = OPC_invokevirtual;
- writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
}
final public void invokevirtual(MethodBinding methodBinding) {
if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$
@@ -3433,13 +4084,13 @@ final public void lconst_1() {
bCodeStream[classFileOffset++] = OPC_lconst_1;
}
final public void ldc(float constant) {
- if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
countLabels = 0;
int index = constantPool.literalIndex(constant);
stackDepth++;
if (stackDepth > stackMax)
stackMax = stackDepth;
if (index > 255) {
+ if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
// Generate a ldc_w
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
@@ -3448,6 +4099,7 @@ final public void ldc(float constant) {
bCodeStream[classFileOffset++] = OPC_ldc_w;
writeUnsignedShort(index);
} else {
+ if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
// Generate a ldc
if (classFileOffset + 1 >= bCodeStream.length) {
resizeByteArray();
@@ -3458,13 +4110,13 @@ final public void ldc(float constant) {
}
}
final public void ldc(int constant) {
- if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
countLabels = 0;
int index = constantPool.literalIndex(constant);
stackDepth++;
if (stackDepth > stackMax)
stackMax = stackDepth;
if (index > 255) {
+ if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
// Generate a ldc_w
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
@@ -3473,6 +4125,7 @@ final public void ldc(int constant) {
bCodeStream[classFileOffset++] = OPC_ldc_w;
writeUnsignedShort(index);
} else {
+ if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
// Generate a ldc
if (classFileOffset + 1 >= bCodeStream.length) {
resizeByteArray();
@@ -3483,7 +4136,6 @@ final public void ldc(int constant) {
}
}
final public void ldc(String constant) {
- if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
countLabels = 0;
int currentConstantPoolIndex = constantPool.currentIndex;
int currentConstantPoolOffset = constantPool.currentOffset;
@@ -3496,6 +4148,7 @@ final public void ldc(String constant) {
if (stackDepth > stackMax)
stackMax = stackDepth;
if (index > 255) {
+ if (DEBUG) System.out.println(position + "\t\tldc_w:"+constant); //$NON-NLS-1$
// Generate a ldc_w
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
@@ -3504,6 +4157,7 @@ final public void ldc(String constant) {
bCodeStream[classFileOffset++] = OPC_ldc_w;
writeUnsignedShort(index);
} else {
+ if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
// Generate a ldc
if (classFileOffset + 1 >= bCodeStream.length) {
resizeByteArray();
@@ -3554,7 +4208,7 @@ final public void ldc(String constant) {
}
// check if all the string is encoded (PR 1PR2DWJ)
// the string is too big to be encoded in one pass
- newStringBuffer();
+ newStringContatenation();
dup();
// write the first part
char[] subChars = new char[i];
@@ -3582,7 +4236,7 @@ final public void ldc(String constant) {
bCodeStream[classFileOffset++] = (byte) index;
}
// write the remaining part
- invokeStringBufferStringConstructor();
+ invokeStringConcatenationStringConstructor();
while (i < constantLength) {
length = 0;
utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)];
@@ -3637,12 +4291,38 @@ final public void ldc(String constant) {
bCodeStream[classFileOffset++] = (byte) index;
}
// now on the stack it should be a StringBuffer and a string.
- invokeStringBufferAppendForType(T_String);
+ invokeStringConcatenationAppendForType(T_JavaLangString);
}
- invokeStringBufferToString();
+ invokeStringConcatenationToString();
invokeStringIntern();
}
}
+final public void ldc(TypeBinding typeBinding) {
+ countLabels = 0;
+ int index = constantPool.literalIndexForType(typeBinding.constantPoolName());
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (index > 255) {
+ if (DEBUG) System.out.println(position + "\t\tldc_w:"+ typeBinding); //$NON-NLS-1$
+ // Generate a ldc_w
+ if (classFileOffset + 2 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ writeUnsignedShort(index);
+ } else {
+ if (DEBUG) System.out.println(position + "\t\tldw:"+ typeBinding); //$NON-NLS-1$
+ // Generate a ldc
+ if (classFileOffset + 1 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position += 2;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ bCodeStream[classFileOffset++] = (byte) index;
+ }
+}
final public void ldc2_w(double constant) {
if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
countLabels = 0;
@@ -4287,14 +4967,14 @@ final public void multianewarray(TypeBinding typeBinding, int dimensions) {
}
position += 2;
bCodeStream[classFileOffset++] = OPC_multianewarray;
- writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
bCodeStream[classFileOffset++] = (byte) dimensions;
}
/**
* We didn't call it new, because there is a conflit with the new keyword
*/
final public void new_(TypeBinding typeBinding) {
- if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding); //$NON-NLS-1$
+ if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding.debugName()); //$NON-NLS-1$
countLabels = 0;
stackDepth++;
if (stackDepth > stackMax)
@@ -4304,7 +4984,7 @@ final public void new_(TypeBinding typeBinding) {
}
position++;
bCodeStream[classFileOffset++] = OPC_new;
- writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName()));
}
final public void newarray(int array_Type) {
if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$
@@ -4316,32 +4996,32 @@ final public void newarray(int array_Type) {
bCodeStream[classFileOffset++] = OPC_newarray;
bCodeStream[classFileOffset++] = (byte) array_Type;
}
-public void newArray(Scope scope, ArrayBinding arrayBinding) {
- TypeBinding component = arrayBinding.elementsType(scope);
+public void newArray(ArrayBinding arrayBinding) {
+ TypeBinding component = arrayBinding.elementsType();
switch (component.id) {
case T_int :
- this.newarray(10);
+ this.newarray(INT_ARRAY);
break;
case T_byte :
- this.newarray(8);
+ this.newarray(BYTE_ARRAY);
break;
case T_boolean :
- this.newarray(4);
+ this.newarray(BOOLEAN_ARRAY);
break;
case T_short :
- this.newarray(9);
+ this.newarray(SHORT_ARRAY);
break;
case T_char :
- this.newarray(5);
+ this.newarray(CHAR_ARRAY);
break;
case T_long :
- this.newarray(11);
+ this.newarray(LONG_ARRAY);
break;
case T_float :
- this.newarray(6);
+ this.newarray(FLOAT_ARRAY);
break;
case T_double :
- this.newarray(7);
+ this.newarray(DOUBLE_ARRAY);
break;
default :
this.anewarray(component);
@@ -4359,7 +5039,7 @@ public void newJavaLangError() {
}
position++;
bCodeStream[classFileOffset++] = OPC_new;
- writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangErrorConstantPoolName));
}
public void newJavaLangAssertionError() {
@@ -4374,9 +5054,22 @@ public void newJavaLangAssertionError() {
}
position++;
bCodeStream[classFileOffset++] = OPC_new;
- writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangAssertionErrorConstantPoolName));
+}
+public void newJavaLangIllegalArgumentException() {
+ // new: java.lang.IllegalArgumentException
+ if (DEBUG) System.out.println(position + "\t\tnew: java.lang.IllegalArgumentException"); //$NON-NLS-1$
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (classFileOffset + 2 >= bCodeStream.length) {
+ resizeByteArray();
+ }
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName));
}
-
public void newNoClassDefFoundError() {
// new: java.lang.NoClassDefFoundError
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$
@@ -4389,21 +5082,33 @@ public void newNoClassDefFoundError() {
}
position++;
bCodeStream[classFileOffset++] = OPC_new;
- writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangNoClassDefFoundErrorConstantPoolName));
}
-public void newStringBuffer() {
+public void newStringContatenation() {
// new: java.lang.StringBuffer
- if (DEBUG) System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+ // new: java.lang.StringBuilder
+ if (DEBUG) {
+ if (this.targetLevel >= JDK1_5) {
+ System.out.println(position + "\t\tnew: java.lang.StringBuilder"); //$NON-NLS-1$
+ } else {
+ System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+ }
+ }
countLabels = 0;
stackDepth++;
- if (stackDepth > stackMax)
+ if (stackDepth > stackMax) {
stackMax = stackDepth;
+ }
if (classFileOffset + 2 >= bCodeStream.length) {
resizeByteArray();
}
position++;
bCodeStream[classFileOffset++] = OPC_new;
- writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer());
+ if (this.targetLevel >= JDK1_5) {
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBuilderConstantPoolName));
+ } else {
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangStringBufferConstantPoolName));
+ }
}
public void newWrapperFor(int typeID) {
countLabels = 0;
@@ -4418,39 +5123,39 @@ public void newWrapperFor(int typeID) {
switch (typeID) {
case T_int : // new: java.lang.Integer
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangIntegerConstantPoolName));
break;
case T_boolean : // new: java.lang.Boolean
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangBooleanConstantPoolName));
break;
case T_byte : // new: java.lang.Byte
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangByteConstantPoolName));
break;
case T_char : // new: java.lang.Character
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangCharacterConstantPoolName));
break;
case T_float : // new: java.lang.Float
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangFloatConstantPoolName));
break;
case T_double : // new: java.lang.Double
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangDoubleConstantPoolName));
break;
case T_short : // new: java.lang.Short
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangShortConstantPoolName));
break;
case T_long : // new: java.lang.Long
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangLongConstantPoolName));
break;
case T_void : // new: java.lang.Void
if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$
- writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
+ writeUnsignedShort(constantPool.literalIndexForType(ConstantPool.JavaLangVoidConstantPoolName));
}
}
final public void nop() {
@@ -4484,37 +5189,29 @@ final public void pop2() {
}
final public void putfield(FieldBinding fieldBinding) {
if (DEBUG) System.out.println(position + "\t\tputfield:"+fieldBinding); //$NON-NLS-1$
- countLabels = 0;
- int id;
- if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
- stackDepth -= 3;
- else
- stackDepth -= 2;
- if (stackDepth > stackMax)
- stackMax = stackDepth;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ int returnTypeSize = 1;
+ if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+ returnTypeSize = 2;
}
- position++;
- bCodeStream[classFileOffset++] = OPC_putfield;
- writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+ generateFieldAccess(
+ OPC_putfield,
+ returnTypeSize,
+ fieldBinding.declaringClass.constantPoolName(),
+ fieldBinding.name,
+ fieldBinding.type.signature());
}
final public void putstatic(FieldBinding fieldBinding) {
if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$
- countLabels = 0;
- int id;
- if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
- stackDepth -= 2;
- else
- stackDepth -= 1;
- if (stackDepth > stackMax)
- stackMax = stackDepth;
- if (classFileOffset + 2 >= bCodeStream.length) {
- resizeByteArray();
+ int returnTypeSize = 1;
+ if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+ returnTypeSize = 2;
}
- position++;
- bCodeStream[classFileOffset++] = OPC_putstatic;
- writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+ generateFieldAccess(
+ OPC_putstatic,
+ returnTypeSize,
+ fieldBinding.declaringClass.constantPoolName(),
+ fieldBinding.name,
+ fieldBinding.type.signature());
}
public void record(LocalVariableBinding local) {
if (!generateLocalVariableTableAttributes)
@@ -4574,15 +5271,14 @@ public void recordPositionsFrom(int startPC, int sourcePos) {
if (existingEntryIndex != -1) {
// widen existing entry
pcToSourceMap[existingEntryIndex] = startPC;
- } else {
+ } else if (insertionIndex < 1 || pcToSourceMap[insertionIndex - 1] != newLine) {
// we have to add an entry that won't be sorted. So we sort the pcToSourceMap.
System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - insertionIndex);
pcToSourceMap[insertionIndex++] = startPC;
pcToSourceMap[insertionIndex] = newLine;
pcToSourceMapSize += 2;
}
- }
- if (position != lastEntryPC) { // no bytecode since last entry pc
+ } else if (position != lastEntryPC) { // no bytecode since last entry pc
pcToSourceMap[pcToSourceMapSize++] = lastEntryPC;
pcToSourceMap[pcToSourceMapSize++] = newLine;
}
@@ -4630,12 +5326,22 @@ public void recordPositionsFrom(int startPC, int sourcePos) {
*/
public void registerExceptionHandler(ExceptionLabel anExceptionLabel) {
int length;
- if (exceptionHandlersNumber >= (length = exceptionHandlers.length)) {
+ if (exceptionHandlersIndex >= (length = exceptionHandlers.length)) {
// resize the exception handlers table
System.arraycopy(exceptionHandlers, 0, exceptionHandlers = new ExceptionLabel[length + LABELS_INCREMENT], 0, length);
}
// no need to resize. So just add the new exception label
- exceptionHandlers[exceptionHandlersNumber++] = anExceptionLabel;
+ exceptionHandlers[exceptionHandlersIndex++] = anExceptionLabel;
+ exceptionHandlersCounter++;
+}
+public void removeExceptionHandler(ExceptionLabel exceptionLabel) {
+ for (int i = 0; i < exceptionHandlersIndex; i++) {
+ if (exceptionHandlers[i] == exceptionLabel) {
+ exceptionHandlers[i] = null;
+ exceptionHandlersCounter--;
+ return;
+ }
+ }
}
public final void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
// given some flow info, make sure we did not loose some variables initialization
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/src/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 66a2f72..a4a4509 100644
--- a/src/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/src/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -10,12 +10,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.codegen;
-import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.ClassFile;
-
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
/**
* This type is used to store all the constant pool entries.
*/
@@ -26,9 +28,7 @@ public class ConstantPool implements ClassFileConstants, TypeIds {
public static final int LONG_INITIAL_SIZE = 5;
public static final int UTF8_INITIAL_SIZE = 778;
public static final int STRING_INITIAL_SIZE = 761;
- public static final int FIELD_INITIAL_SIZE = 156;
- public static final int METHOD_INITIAL_SIZE = 236;
- public static final int INTERFACE_INITIAL_SIZE = 50;
+ public static final int METHODS_AND_FIELDS_INITIAL_SIZE = 450;
public static final int CLASS_INITIAL_SIZE = 86;
public static final int NAMEANDTYPE_INITIAL_SIZE = 272;
public static final int CONSTANTPOOL_INITIAL_SIZE = 2000;
@@ -39,131 +39,200 @@ public class ConstantPool implements ClassFileConstants, TypeIds {
protected LongCache longCache;
public CharArrayCache UTF8Cache;
protected CharArrayCache stringCache;
- protected ObjectCache fieldCache;
- protected ObjectCache methodCache;
- protected ObjectCache interfaceMethodCache;
- protected ObjectCache classCache;
- protected FieldNameAndTypeCache nameAndTypeCacheForFields;
- protected MethodNameAndTypeCache nameAndTypeCacheForMethods;
- int[] wellKnownTypes = new int[21];
- int[] wellKnownMethods = new int[36];
- int[] wellKnownFields = new int[10];
- int[] wellKnownFieldNameAndTypes = new int[2];
- int[] wellKnownMethodNameAndTypes = new int[33];
+ protected HashtableOfObject methodsAndFieldsCache;
+ protected CharArrayCache classCache;
+ protected HashtableOfObject nameAndTypeCacheForFieldsAndMethods;
public byte[] poolContent;
public int currentIndex = 1;
public int currentOffset;
- // predefined constant index for well known types
- final static int JAVA_LANG_BOOLEAN_TYPE = 0;
- final static int JAVA_LANG_BYTE_TYPE = 1;
- final static int JAVA_LANG_CHARACTER_TYPE = 2;
- final static int JAVA_LANG_DOUBLE_TYPE = 3;
- final static int JAVA_LANG_FLOAT_TYPE = 4;
- final static int JAVA_LANG_INTEGER_TYPE = 5;
- final static int JAVA_LANG_LONG_TYPE = 6;
- final static int JAVA_LANG_SHORT_TYPE = 7;
- final static int JAVA_LANG_VOID_TYPE = 8;
- final static int JAVA_LANG_CLASS_TYPE = 9;
- final static int JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE = 10;
- final static int JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE = 11;
- final static int JAVA_LANG_OBJECT_TYPE = 12;
- final static int JAVA_LANG_STRING_TYPE = 13;
- final static int JAVA_LANG_STRINGBUFFER_TYPE = 14;
- final static int JAVA_LANG_SYSTEM_TYPE = 15;
- final static int JAVA_LANG_THROWABLE_TYPE = 16;
- final static int JAVA_LANG_ERROR_TYPE = 17;
- final static int JAVA_LANG_EXCEPTION_TYPE = 18;
- final static int JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE = 19;
- final static int JAVA_LANG_ASSERTIONERROR_TYPE = 20;
-
- // predefined constant index for well known fields
- final static int TYPE_BYTE_FIELD = 0;
- final static int TYPE_SHORT_FIELD = 1;
- final static int TYPE_CHARACTER_FIELD = 2;
- final static int TYPE_INTEGER_FIELD = 3;
- final static int TYPE_LONG_FIELD = 4;
- final static int TYPE_FLOAT_FIELD = 5;
- final static int TYPE_DOUBLE_FIELD = 6;
- final static int TYPE_BOOLEAN_FIELD = 7;
- final static int TYPE_VOID_FIELD = 8;
- final static int OUT_SYSTEM_FIELD = 9;
- // predefined constant index for well known methods
- final static int FORNAME_CLASS_METHOD = 0;
- final static int NOCLASSDEFFOUNDERROR_CONSTR_METHOD = 1;
- final static int APPEND_INT_METHOD = 2;
- final static int APPEND_FLOAT_METHOD = 3;
- final static int APPEND_LONG_METHOD = 4;
- final static int APPEND_OBJECT_METHOD = 5;
- final static int APPEND_CHAR_METHOD = 6;
- final static int APPEND_STRING_METHOD = 7;
- final static int APPEND_BOOLEAN_METHOD = 8;
- final static int APPEND_DOUBLE_METHOD = 9;
- final static int STRINGBUFFER_STRING_CONSTR_METHOD = 10;
- final static int STRINGBUFFER_DEFAULT_CONSTR_METHOD = 11;
- final static int STRINGBUFFER_TOSTRING_METHOD = 12;
- final static int SYSTEM_EXIT_METHOD = 13;
- final static int THROWABLE_GETMESSAGE_METHOD = 14;
- final static int JAVALANGERROR_CONSTR_METHOD = 15;
- final static int NEWINSTANCE_CONSTRUCTOR_METHOD = 16;
- final static int STRING_INTERN_METHOD = 17;
- final static int VALUEOF_INT_METHOD = 18;
- final static int VALUEOF_FLOAT_METHOD = 19;
- final static int VALUEOF_LONG_METHOD = 20;
- final static int VALUEOF_OBJECT_METHOD = 21;
- final static int VALUEOF_CHAR_METHOD = 22;
- final static int VALUEOF_BOOLEAN_METHOD = 23;
- final static int VALUEOF_DOUBLE_METHOD = 24;
- final static int ASSERTIONERROR_CONSTR_OBJECT_METHOD = 25;
- final static int ASSERTIONERROR_CONSTR_INT_METHOD = 26;
- final static int ASSERTIONERROR_CONSTR_LONG_METHOD = 27;
- final static int ASSERTIONERROR_CONSTR_FLOAT_METHOD = 28;
- final static int ASSERTIONERROR_CONSTR_DOUBLE_METHOD = 29;
- final static int ASSERTIONERROR_CONSTR_BOOLEAN_METHOD = 30;
- final static int ASSERTIONERROR_CONSTR_CHAR_METHOD = 31;
- final static int ASSERTIONERROR_DEFAULT_CONSTR_METHOD = 32;
- final static int DESIREDASSERTIONSTATUS_CLASS_METHOD = 33;
- final static int GETCLASS_OBJECT_METHOD = 34;
- final static int GETCOMPONENTTYPE_CLASS_METHOD = 35;
-
- // predefined constant index for well known name and type for fields
- final static int TYPE_JAVALANGCLASS_NAME_AND_TYPE = 0;
- final static int OUT_SYSTEM_NAME_AND_TYPE = 1;
- // predefined constant index for well known name and type for methods
- final static int FORNAME_CLASS_METHOD_NAME_AND_TYPE = 0;
- final static int CONSTR_STRING_METHOD_NAME_AND_TYPE = 1;
- final static int DEFAULT_CONSTR_METHOD_NAME_AND_TYPE = 2;
- final static int APPEND_INT_METHOD_NAME_AND_TYPE = 3;
- final static int APPEND_FLOAT_METHOD_NAME_AND_TYPE = 4;
- final static int APPEND_LONG_METHOD_NAME_AND_TYPE = 5;
- final static int APPEND_OBJECT_METHOD_NAME_AND_TYPE = 6;
- final static int APPEND_CHAR_METHOD_NAME_AND_TYPE = 7;
- final static int APPEND_STRING_METHOD_NAME_AND_TYPE = 8;
- final static int APPEND_BOOLEAN_METHOD_NAME_AND_TYPE = 9;
- final static int APPEND_DOUBLE_METHOD_NAME_AND_TYPE = 10;
- final static int TOSTRING_METHOD_NAME_AND_TYPE = 11;
- final static int EXIT_METHOD_NAME_AND_TYPE = 12;
- final static int GETMESSAGE_METHOD_NAME_AND_TYPE = 13;
- final static int NEWINSTANCE_METHOD_NAME_AND_TYPE = 14;
- final static int INTERN_METHOD_NAME_AND_TYPE = 15;
- final static int VALUEOF_INT_METHOD_NAME_AND_TYPE = 16;
- final static int VALUEOF_FLOAT_METHOD_NAME_AND_TYPE = 17;
- final static int VALUEOF_LONG_METHOD_NAME_AND_TYPE = 18;
- final static int VALUEOF_OBJECT_METHOD_NAME_AND_TYPE = 19;
- final static int VALUEOF_CHAR_METHOD_NAME_AND_TYPE = 20;
- final static int VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE = 21;
- final static int VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE = 22;
- final static int CONSTR_INT_METHOD_NAME_AND_TYPE = 23;
- final static int CONSTR_LONG_METHOD_NAME_AND_TYPE = 24;
- final static int CONSTR_FLOAT_METHOD_NAME_AND_TYPE = 25;
- final static int CONSTR_DOUBLE_METHOD_NAME_AND_TYPE = 26;
- final static int CONSTR_OBJECT_METHOD_NAME_AND_TYPE = 27;
- final static int CONSTR_CHAR_METHOD_NAME_AND_TYPE = 28;
- final static int CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
- final static int DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE = 30;
- final static int GETCLASS_OBJECT_METHOD_NAME_AND_TYPE = 31;
- final static int GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE = 32;
-
+
public ClassFile classFile;
+ public static final char[] Append = "append".toCharArray(); //$NON-NLS-1$
+ public static final char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
+ public static final char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ArrayCopy = "arraycopy".toCharArray(); //$NON-NLS-1$
+ public static final char[] ArrayCopySignature = "(Ljava/lang/Object;ILjava/lang/Object;II)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] ArrayJavaLangClassConstantPoolName = "[Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ArrayJavaLangObjectConstantPoolName = "[Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[] booleanBooleanSignature = "(Z)Ljava/lang/Boolean;".toCharArray(); //$NON-NLS-1$
+ public static final char[] BooleanConstrSignature = "(Z)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
+ public static final char[] byteByteSignature = "(B)Ljava/lang/Byte;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
+ public static final char[] charCharacterSignature = "(C)Ljava/lang/Character;".toCharArray(); //$NON-NLS-1$
+ public static final char[] CharConstrSignature = "(C)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
+ public static final char[] Clinit = "".toCharArray(); //$NON-NLS-1$
+ public static final char[] DefaultConstructorSignature = "()V".toCharArray(); //$NON-NLS-1$
+ public static final char[] ClinitSignature = DefaultConstructorSignature;
+ public static final char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
+ public static final char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
+ public static final char[] DoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] doubleDoubleSignature = "(D)Ljava/lang/Double;".toCharArray(); //$NON-NLS-1$
+ public static final char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
+ public static final char[] Equals = "equals".toCharArray(); //$NON-NLS-1$
+ public static final char[] EqualsSignature = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
+ public static final char[] Exit = "exit".toCharArray(); //$NON-NLS-1$
+ public static final char[] ExitIntSignature = "(I)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] FloatConstrSignature = "(F)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] floatFloatSignature = "(F)Ljava/lang/Float;".toCharArray(); //$NON-NLS-1$
+ public static final char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
+ public static final char[] ForName = "forName".toCharArray(); //$NON-NLS-1$
+ public static final char[] ForNameSignature = "(Ljava/lang/String;)Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
+ public static final char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetComponentTypeSignature = GetClassSignature;
+ public static final char[] GetConstructor = "getConstructor".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetConstructorSignature = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
+ public static final char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
+ // predefined methods constant names
+ public static final char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
+ public static final char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
+ public static final char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetMessage = "getMessage".toCharArray(); //$NON-NLS-1$
+ public static final char[] GetMessageSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] HasNext = "hasNext".toCharArray();//$NON-NLS-1$
+ public static final char[] HasNextSignature = "()Z".toCharArray();//$NON-NLS-1$
+ public static final char[] Init = "".toCharArray(); //$NON-NLS-1$
+ public static final char[] IntConstrSignature = "(I)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] Intern = "intern".toCharArray(); //$NON-NLS-1$
+ public static final char[] InternSignature = GetMessageSignature;
+ public static final char[] IntIntegerSignature = "(I)Ljava/lang/Integer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
+ public static final char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
+ public static final char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
+ public static final char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
+ // predefined type constant names
+ public static final char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
+ public static final char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {TypeConstants.JAVA, TypeConstants.LANG, TypeConstants.REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
+ public static final char[] JavaIoPrintStreamSignature = "Ljava/io/PrintStream;".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangAssertionErrorConstantPoolName = "java/lang/AssertionError".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangBooleanConstantPoolName = "java/lang/Boolean".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangByteConstantPoolName = "java/lang/Byte".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangCharacterConstantPoolName = "java/lang/Character".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangClassConstantPoolName = "java/lang/Class".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangClassNotFoundExceptionConstantPoolName = "java/lang/ClassNotFoundException".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangClassSignature = "Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangDoubleConstantPoolName = "java/lang/Double".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangErrorConstantPoolName = "java/lang/Error".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangExceptionConstantPoolName = "java/lang/Exception".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangFloatConstantPoolName = "java/lang/Float".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangIllegalArgumentExceptionConstantPoolName = "java/lang/IllegalArgumentException".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangIntegerConstantPoolName = "java/lang/Integer".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangLongConstantPoolName = "java/lang/Long".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangNoClassDefFoundErrorConstantPoolName = "java/lang/NoClassDefFoundError".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangObjectConstantPoolName = "java/lang/Object".toCharArray(); //$NON-NLS-1$
+ public static final char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
+ public static final char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangReflectConstructor = "java/lang/reflect/Constructor".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangReflectConstructorNewInstanceSignature = "([Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
+ public static final char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangShortConstantPoolName = "java/lang/Short".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangStringBufferConstantPoolName = "java/lang/StringBuffer".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangStringBuilderConstantPoolName = "java/lang/StringBuilder".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangStringConstantPoolName = "java/lang/String".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangStringSignature = "Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangSystemConstantPoolName = "java/lang/System".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangThrowableConstantPoolName = "java/lang/Throwable".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaLangVoidConstantPoolName = "java/lang/Void".toCharArray(); //$NON-NLS-1$
+ public static final char[] JavaUtilIteratorConstantPoolName = "java/util/Iterator".toCharArray(); //$NON-NLS-1$
+ public static final char[] LongConstrSignature = "(J)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] longLongSignature = "(J)Ljava/lang/Long;".toCharArray(); //$NON-NLS-1$
+ public static final char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
+ public static final char[] Name = "name".toCharArray(); //$NON-NLS-1$
+ public static final char[] NameSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] NewInstance = "newInstance".toCharArray(); //$NON-NLS-1$
+ public static final char[] NewInstanceSignature = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+ public static final char[] Next = "next".toCharArray();//$NON-NLS-1$
+ public static final char[] NextSignature = "()Ljava/lang/Object;".toCharArray();//$NON-NLS-1$
+ public static final char[] ObjectConstrSignature = "(Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] Ordinal = "ordinal".toCharArray(); //$NON-NLS-1$
+ public static final char[] OrdinalSignature = "()I".toCharArray(); //$NON-NLS-1$
+ public static final char[] Out = "out".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
+ public static final char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
+ public static final char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] ShortConstrSignature = "(S)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] shortShortSignature = "(S)Ljava/lang/Short;".toCharArray(); //$NON-NLS-1$
+ public static final char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
+ public static final char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendBooleanSignature = "(Z)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendCharSignature = "(C)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendDoubleSignature = "(D)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendFloatSignature = "(F)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendIntSignature = "(I)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendLongSignature = "(J)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBufferAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendBooleanSignature = "(Z)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendCharSignature = "(C)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendDoubleSignature = "(D)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendFloatSignature = "(F)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendIntSignature = "(I)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendLongSignature = "(J)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringBuilderAppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuilder;".toCharArray(); //$NON-NLS-1$
+ public static final char[] StringConstructorSignature = "(Ljava/lang/String;)V".toCharArray(); //$NON-NLS-1$
+ public static final char[] This = "this".toCharArray(); //$NON-NLS-1$
+ public static final char[] ToString = "toString".toCharArray(); //$NON-NLS-1$
+ public static final char[] ToStringSignature = GetMessageSignature;
+ public static final char[] TYPE = "TYPE".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOf = "valueOf".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfBooleanSignature = "(Z)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfCharSignature = "(C)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfDoubleSignature = "(D)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfFloatSignature = "(F)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfIntSignature = "(I)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfLongSignature = "(J)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
+ public static final char[] ValueOfObjectSignature = "(Ljava/lang/Object;)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
/**
* ConstantPool constructor comment.
@@ -171,12 +240,9 @@ public class ConstantPool implements ClassFileConstants, TypeIds {
public ConstantPool(ClassFile classFile) {
this.UTF8Cache = new CharArrayCache(UTF8_INITIAL_SIZE);
this.stringCache = new CharArrayCache(STRING_INITIAL_SIZE);
- this.fieldCache = new ObjectCache(FIELD_INITIAL_SIZE);
- this.methodCache = new ObjectCache(METHOD_INITIAL_SIZE);
- this.interfaceMethodCache = new ObjectCache(INTERFACE_INITIAL_SIZE);
- this.classCache = new ObjectCache(CLASS_INITIAL_SIZE);
- this.nameAndTypeCacheForMethods = new MethodNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);
- this.nameAndTypeCacheForFields = new FieldNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);
+ this.methodsAndFieldsCache = new HashtableOfObject(METHODS_AND_FIELDS_INITIAL_SIZE);
+ this.classCache = new CharArrayCache(CLASS_INITIAL_SIZE);
+ this.nameAndTypeCacheForFieldsAndMethods = new HashtableOfObject(NAMEANDTYPE_INITIAL_SIZE);
this.poolContent = classFile.header;
this.currentOffset = classFile.headerOffset;
// currentOffset is initialized to 0 by default
@@ -190,440 +256,23 @@ public byte[] dumpBytes() {
System.arraycopy(poolContent, 0, (poolContent = new byte[currentOffset]), 0, currentOffset);
return poolContent;
}
-/**
- * Return the index of the @fieldBinding.
- *
- * Returns -1 if the @fieldBinding is not a predefined fieldBinding,
- * the right index otherwise.
- *
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return int
- */
-public int indexOfWellKnownFieldNameAndType(FieldBinding fieldBinding) {
- if ((fieldBinding.type.id == T_JavaLangClass) && (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE)))
- return TYPE_JAVALANGCLASS_NAME_AND_TYPE;
- if ((fieldBinding.type.id == T_JavaIoPrintStream) && (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.Out)))
- return OUT_SYSTEM_NAME_AND_TYPE;
- return -1;
-}
-/**
- * Return the index of the @fieldBinding.
- *
- * Returns -1 if the @fieldBinding is not a predefined fieldBinding,
- * the right index otherwise.
- *
- * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return int
- */
-public int indexOfWellKnownFields(FieldBinding fieldBinding) {
- switch (fieldBinding.declaringClass.id) {
- case T_JavaLangByte :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_BYTE_FIELD;
- break;
- case T_JavaLangShort :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_SHORT_FIELD;
- break;
- case T_JavaLangCharacter :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_CHARACTER_FIELD;
- break;
- case T_JavaLangInteger :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_INTEGER_FIELD;
- break;
- case T_JavaLangLong :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_LONG_FIELD;
- break;
- case T_JavaLangFloat :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_FLOAT_FIELD;
- break;
- case T_JavaLangDouble :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_DOUBLE_FIELD;
- break;
- case T_JavaLangBoolean :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_BOOLEAN_FIELD;
- break;
- case T_JavaLangVoid :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.TYPE))
- return TYPE_VOID_FIELD;
- break;
- case T_JavaLangSystem :
- if (CharOperation.equals(fieldBinding.name, QualifiedNamesConstants.Out))
- return OUT_SYSTEM_FIELD;
- }
- return -1;
-}
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding,
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int indexOfWellKnownMethodNameAndType(MethodBinding methodBinding) {
- char firstChar = methodBinding.selector[0];
- switch (firstChar) {
- case 'f' :
- if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (methodBinding.returnType.id == T_JavaLangClass) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ForName))) {
- // This method binding is forName(java.lang.String)
- return FORNAME_CLASS_METHOD_NAME_AND_TYPE;
- }
- break;
- case '<' :
- if (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) {
- switch(methodBinding.parameters.length) {
- case 1:
- switch(methodBinding.parameters[0].id) {
- case T_String :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.StringConstructorSignature)) {
- return CONSTR_STRING_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_Object :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorObjectConstrSignature)) {
- return CONSTR_OBJECT_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_int :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorIntConstrSignature)) {
- return CONSTR_INT_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_char :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorCharConstrSignature)) {
- return CONSTR_CHAR_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_boolean :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorBooleanConstrSignature)) {
- return CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_float :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorFloatConstrSignature)) {
- return CONSTR_FLOAT_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_double :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorDoubleConstrSignature)) {
- return CONSTR_DOUBLE_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- case T_long :
- if (CharOperation.equals(methodBinding.signature(), QualifiedNamesConstants.AssertionErrorLongConstrSignature)) {
- return CONSTR_LONG_METHOD_NAME_AND_TYPE;
- } else {
- return -1;
- }
- }
- case 0:
- if (methodBinding.signature().length == 3) {
- return DEFAULT_CONSTR_METHOD_NAME_AND_TYPE;
- }
- }
- }
- break;
- case 'a' :
- if ((methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangStringBuffer) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Append))) {
- switch (methodBinding.parameters[0].id) {
- case T_int :
- case T_byte :
- case T_short :
- // This method binding is append(int)
- return APPEND_INT_METHOD_NAME_AND_TYPE;
- case T_float :
- // This method binding is append(float)
- return APPEND_FLOAT_METHOD_NAME_AND_TYPE;
- case T_long :
- // This method binding is append(long)
- return APPEND_LONG_METHOD_NAME_AND_TYPE;
- case T_JavaLangObject :
- // This method binding is append(java.lang.Object)
- return APPEND_OBJECT_METHOD_NAME_AND_TYPE;
- case T_char :
- // This method binding is append(char)
- return APPEND_CHAR_METHOD_NAME_AND_TYPE;
- case T_JavaLangString :
- // This method binding is append(java.lang.String)
- return APPEND_STRING_METHOD_NAME_AND_TYPE;
- case T_boolean :
- // This method binding is append(boolean)
- return APPEND_BOOLEAN_METHOD_NAME_AND_TYPE;
- case T_double :
- // This method binding is append(double)
- return APPEND_DOUBLE_METHOD_NAME_AND_TYPE;
- }
- }
- break;
- case 't' :
- if ((methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ToString))) {
- // This method binding is toString()
- return TOSTRING_METHOD_NAME_AND_TYPE;
- }
- break;
- case 'v' :
- if ((methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ValueOf))) {
- switch(methodBinding.parameters[0].id) {
- case T_Object:
- return VALUEOF_OBJECT_METHOD_NAME_AND_TYPE;
- case T_int:
- case T_short:
- case T_byte:
- return VALUEOF_INT_METHOD_NAME_AND_TYPE;
- case T_long:
- return VALUEOF_LONG_METHOD_NAME_AND_TYPE;
- case T_float:
- return VALUEOF_FLOAT_METHOD_NAME_AND_TYPE;
- case T_double:
- return VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE;
- case T_boolean:
- return VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE;
- case T_char:
- return VALUEOF_CHAR_METHOD_NAME_AND_TYPE;
- }
- }
- break;
- case 'e' :
- if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_int) && (methodBinding.returnType.id == T_void) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Exit))) {
- // This method binding is exit(int)
- return EXIT_METHOD_NAME_AND_TYPE;
- }
- break;
- case 'g' :
- if ((methodBinding.selector.length == 10)
- && (methodBinding.parameters.length == 0)
- && (methodBinding.returnType.id == T_JavaLangString)
- && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetMessage))) {
- // This method binding is getMessage()
- return GETMESSAGE_METHOD_NAME_AND_TYPE;
- }
- if (methodBinding.parameters.length == 0
- && methodBinding.returnType.id == T_JavaLangClass
- && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetClass)) {
- return GETCLASS_OBJECT_METHOD_NAME_AND_TYPE;
- }
- if (methodBinding.parameters.length == 0
- && methodBinding.returnType.id == T_JavaLangClass
- && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
- return GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE;
- }
- break;
- case 'i' :
- if ((methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Intern))) {
- // This method binding is toString()
- return INTERN_METHOD_NAME_AND_TYPE;
- }
+private int getFromCache(char[] declaringClass, char[] name, char[] signature) {
+ HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(declaringClass);
+ if (value == null) {
+ return -1;
}
- return -1;
-}
-/**
- * Return the index of the @methodBinding.
- *
- * Returns -1 if the @methodBinding is not a predefined methodBinding,
- * the right index otherwise.
- *
- * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int indexOfWellKnownMethods(MethodBinding methodBinding) {
- char firstChar = methodBinding.selector[0];
- switch (methodBinding.declaringClass.id) {
- case T_JavaLangClass :
- if ((firstChar == 'f') && (methodBinding.isStatic()) && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (methodBinding.returnType.id == T_JavaLangClass) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ForName))) {
- // This method binding is forName(java.lang.String)
- return FORNAME_CLASS_METHOD;
- } else if ((firstChar == 'd') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_boolean) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.DesiredAssertionStatus)) {
- return DESIREDASSERTIONSTATUS_CLASS_METHOD;
- } else if ((firstChar == 'g') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangClass) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
- return GETCOMPONENTTYPE_CLASS_METHOD;
- }
- break;
- case T_JavaLangNoClassDefError :
- if ((firstChar == '<') && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init))) {
- // This method binding is NoClassDefFoundError(java.lang.String)
- return NOCLASSDEFFOUNDERROR_CONSTR_METHOD;
- }
- break;
- case T_JavaLangReflectConstructor :
- if ((firstChar == 'n') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangObject) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.NewInstance) && CharOperation.equals(methodBinding.parameters[0].constantPoolName(), QualifiedNamesConstants.ArrayJavaLangObjectConstantPoolName)) {
- return NEWINSTANCE_CONSTRUCTOR_METHOD;
- }
- break;
- case T_JavaLangStringBuffer :
- if ((firstChar == 'a') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangStringBuffer) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Append))) {
- switch (methodBinding.parameters[0].id) {
- case T_int :
- case T_byte :
- case T_short :
- // This method binding is append(int)
- return APPEND_INT_METHOD;
- case T_float :
- // This method binding is append(float)
- return APPEND_FLOAT_METHOD;
- case T_long :
- // This method binding is append(long)
- return APPEND_LONG_METHOD;
- case T_JavaLangObject :
- // This method binding is append(java.lang.Object)
- return APPEND_OBJECT_METHOD;
- case T_char :
- // This method binding is append(char)
- return APPEND_CHAR_METHOD;
- case T_JavaLangString :
- // This method binding is append(java.lang.String)
- return APPEND_STRING_METHOD;
- case T_boolean :
- // This method binding is append(boolean)
- return APPEND_BOOLEAN_METHOD;
- case T_double :
- // This method binding is append(double)
- return APPEND_DOUBLE_METHOD;
- }
- } else
- if ((firstChar == 't') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ToString))) {
- // This method binding is toString()
- return STRINGBUFFER_TOSTRING_METHOD;
- } else
- if ((firstChar == '<') && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init))) {
- if ((methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_JavaLangString)) {
- // This method binding is (String)
- return STRINGBUFFER_STRING_CONSTR_METHOD;
- } else {
- if (methodBinding.parameters.length == 0) {
- // This method binding is ()
- return STRINGBUFFER_DEFAULT_CONSTR_METHOD;
- }
- }
- }
- break;
- case T_JavaLangString :
- if ((firstChar == 'v') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.ValueOf))) {
- // This method binding is valueOf(java.lang.Object)
- switch (methodBinding.parameters[0].id) {
- case T_Object :
- return VALUEOF_OBJECT_METHOD;
- case T_int :
- case T_short :
- case T_byte :
- return VALUEOF_INT_METHOD;
- case T_long :
- return VALUEOF_LONG_METHOD;
- case T_float :
- return VALUEOF_FLOAT_METHOD;
- case T_double :
- return VALUEOF_DOUBLE_METHOD;
- case T_boolean :
- return VALUEOF_BOOLEAN_METHOD;
- case T_char :
- return VALUEOF_CHAR_METHOD;
- }
- } else
- if ((firstChar == 'i') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Intern))) {
- // This method binding is valueOf(java.lang.Object)
- return STRING_INTERN_METHOD;
- }
- break;
- case T_JavaLangSystem :
- if ((firstChar == 'e') && (methodBinding.parameters.length == 1) && (methodBinding.parameters[0].id == T_int) && (methodBinding.returnType.id == T_void) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Exit))) {
- // This method binding is exit(int)
- return SYSTEM_EXIT_METHOD;
- }
- break;
- case T_JavaLangThrowable :
- if ((firstChar == 'g') && (methodBinding.selector.length == 10) && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetMessage))) {
- // This method binding is getMessage()
- return THROWABLE_GETMESSAGE_METHOD;
- }
- break;
- case T_JavaLangError :
- if ((firstChar == '<') && (methodBinding.parameters.length == 1) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) && (methodBinding.parameters[0].id == T_String)) {
- return JAVALANGERROR_CONSTR_METHOD;
- }
- break;
- case T_JavaLangAssertionError :
- if ((firstChar == '<') && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Init)) {
- switch (methodBinding.parameters.length) {
- case 0:
- return ASSERTIONERROR_DEFAULT_CONSTR_METHOD;
- case 1:
- switch(methodBinding.parameters[0].id) {
- case T_boolean :
- return ASSERTIONERROR_CONSTR_BOOLEAN_METHOD;
- case T_char :
- return ASSERTIONERROR_CONSTR_CHAR_METHOD;
- case T_double :
- return ASSERTIONERROR_CONSTR_DOUBLE_METHOD;
- case T_int :
- case T_byte :
- case T_short :
- return ASSERTIONERROR_CONSTR_INT_METHOD;
- case T_float :
- return ASSERTIONERROR_CONSTR_FLOAT_METHOD;
- case T_long :
- return ASSERTIONERROR_CONSTR_LONG_METHOD;
- default:
- return ASSERTIONERROR_CONSTR_OBJECT_METHOD;
- }
- }
- }
- break;
- case T_JavaLangObject :
- if (methodBinding.parameters.length == 0
- && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetClass)) {
- return GETCLASS_OBJECT_METHOD;
- }
+ CharArrayCache value2 = (CharArrayCache) value.get(name);
+ if (value2 == null) {
+ return -1;
}
- return -1;
+ return value2.get(signature);
}
-/**
- * Return the index of the @typeBinding
- *
- * Returns -1 if the @typeBinding is not a predefined binding, the right index
- * otherwise.
- *
- * @param typeBinding org.eclipse.jdt.internal.compiler.lookup.TypeBinding
- * @return int
- */
-public int indexOfWellKnownTypes(TypeBinding typeBinding) {
- switch(typeBinding.id) {
- case T_JavaLangBoolean : return JAVA_LANG_BOOLEAN_TYPE;
- case T_JavaLangByte : return JAVA_LANG_BYTE_TYPE;
- case T_JavaLangCharacter : return JAVA_LANG_CHARACTER_TYPE;
- case T_JavaLangDouble : return JAVA_LANG_DOUBLE_TYPE;
- case T_JavaLangFloat : return JAVA_LANG_FLOAT_TYPE;
- case T_JavaLangInteger : return JAVA_LANG_INTEGER_TYPE;
- case T_JavaLangLong : return JAVA_LANG_LONG_TYPE;
- case T_JavaLangShort : return JAVA_LANG_SHORT_TYPE;
- case T_JavaLangVoid : return JAVA_LANG_VOID_TYPE;
- case T_JavaLangClass : return JAVA_LANG_CLASS_TYPE;
- case T_JavaLangClassNotFoundException : return JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE;
- case T_JavaLangNoClassDefError : return JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE;
- case T_JavaLangObject : return JAVA_LANG_OBJECT_TYPE;
- case T_JavaLangString : return JAVA_LANG_STRING_TYPE;
- case T_JavaLangStringBuffer : return JAVA_LANG_STRINGBUFFER_TYPE;
- case T_JavaLangSystem : return JAVA_LANG_SYSTEM_TYPE;
- case T_JavaLangThrowable : return JAVA_LANG_THROWABLE_TYPE;
- case T_JavaLangError : return JAVA_LANG_ERROR_TYPE;
- case T_JavaLangException : return JAVA_LANG_EXCEPTION_TYPE;
- case T_JavaLangReflectConstructor : return JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE;
- case T_JavaLangAssertionError : return JAVA_LANG_ASSERTIONERROR_TYPE;
+private int getFromNameAndTypeCache(char[] name, char[] signature) {
+ CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(name);
+ if (value == null) {
+ return -1;
}
- return -1;
+ return value.get(signature);
}
public int literalIndex(byte[] utf8encoding, char[] stringCharArray) {
int index;
@@ -908,35 +557,20 @@ public int literalIndex(String stringConstant) {
*/
public int literalIndex(FieldBinding aFieldBinding) {
int index;
- int nameAndTypeIndex;
- int classIndex;
- int indexWellKnownField;
- if ((indexWellKnownField = indexOfWellKnownFields(aFieldBinding)) == -1) {
- if ((index = fieldCache.get(aFieldBinding)) < 0) {
- // The entry doesn't exit yet
- classIndex = literalIndex(aFieldBinding.declaringClass);
- nameAndTypeIndex = literalIndexForFields(literalIndex(aFieldBinding.name), literalIndex(aFieldBinding.type.signature()), aFieldBinding);
- index = fieldCache.put(aFieldBinding, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- } else {
- if ((index = wellKnownFields[indexWellKnownField]) == 0) {
- // that field need to be inserted
- classIndex = literalIndex(aFieldBinding.declaringClass);
- nameAndTypeIndex = literalIndexForFields(literalIndex(aFieldBinding.name), literalIndex(aFieldBinding.type.signature()), aFieldBinding);
- index = wellKnownFields[indexWellKnownField] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
+ final char[] name = aFieldBinding.name;
+ final char[] signature = aFieldBinding.type.signature();
+ final char[] declaringClassConstantPoolName = aFieldBinding.declaringClass.constantPoolName();
+ if ((index = getFromCache(declaringClassConstantPoolName, name, signature)) < 0) {
+ // The entry doesn't exit yet
+ int classIndex = literalIndexForType(declaringClassConstantPoolName);
+ int nameAndTypeIndex = literalIndexForFields(literalIndex(name), literalIndex(signature), name, signature);
+ index = putInCache(declaringClassConstantPoolName, name, signature, currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
+ writeU1(FieldRefTag);
+ writeU2(classIndex);
+ writeU2(nameAndTypeIndex);
}
return index;
}
@@ -951,99 +585,54 @@ public int literalIndex(FieldBinding aFieldBinding) {
*/
public int literalIndex(MethodBinding aMethodBinding) {
int index;
- int nameAndTypeIndex;
- int classIndex;
- int indexWellKnownMethod;
- if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
- if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
- // Lookinf into the interface method ref table
- if ((index = interfaceMethodCache.get(aMethodBinding)) < 0) {
- classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
- nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
- index = interfaceMethodCache.put(aMethodBinding, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the interface method ref constant into the constant pool
- // First add the tag
- writeU1(InterfaceMethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- } else {
- // Lookinf into the method ref table
- if ((index = methodCache.get(aMethodBinding)) < 0) {
- classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
- nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
- index = methodCache.put(aMethodBinding, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- }
- } else {
- // This is a well known method
- if ((index = wellKnownMethods[indexWellKnownMethod]) == 0) {
- // this methods was not inserted yet
- if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
- // Lookinf into the interface method ref table
- classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
- nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
- index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the interface method ref constant into the constant pool
- // First add the tag
- writeU1(InterfaceMethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- } else {
- // Lookinf into the method ref table
- classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
- nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
- index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
+ final TypeBinding constantPoolDeclaringClass = aMethodBinding.constantPoolDeclaringClass();
+ final char[] declaringClassConstantPoolName = constantPoolDeclaringClass.constantPoolName();
+ final char[] selector = aMethodBinding.selector;
+ final char[] signature = aMethodBinding.signature();
+ if ((index = getFromCache(declaringClassConstantPoolName, selector, signature)) < 0) {
+ int classIndex = literalIndexForType(constantPoolDeclaringClass.constantPoolName());
+ int nameAndTypeIndex = literalIndexForMethods(literalIndex(selector), literalIndex(signature), selector, signature);
+ index = putInCache(declaringClassConstantPoolName, selector, signature, currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
+ // Write the interface method ref constant into the constant pool
+ // First add the tag
+ writeU1(constantPoolDeclaringClass.isInterface() || constantPoolDeclaringClass.isAnnotationType() ? InterfaceMethodRefTag : MethodRefTag);
+ // Then write the class index
+ writeU2(classIndex);
+ // The write the nameAndType index
+ writeU2(nameAndTypeIndex);
}
return index;
}
/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param aTypeBinding TypeBinding
- * @return int
+ * This method returns the index into the constantPool corresponding to the type descriptor
+ * corresponding to a type constant pool name.
*/
-public int literalIndex(TypeBinding aTypeBinding) {
+public int literalIndexForType(final char[] constantPoolName) {
int index;
- int nameIndex;
- int indexWellKnownType;
- if ((indexWellKnownType = indexOfWellKnownTypes(aTypeBinding)) == -1) {
- if ((index = classCache.get(aTypeBinding)) < 0) {
+ if ((index = classCache.get(constantPoolName)) < 0) {
+ // The entry doesn't exit yet
+ int nameIndex = literalIndex(constantPoolName);
+ index = classCache.put(constantPoolName, currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+ }
+ writeU1(ClassTag);
+ // Then add the 8 bytes representing the long
+ writeU2(nameIndex);
+ }
+ return index;
+}
+public int literalIndexForMethod(char[] declaringClass, char[] selector, char[] signature, boolean isInterface) {
+ int index = getFromCache(declaringClass, selector, signature);
+ if (index == -1) {
+ int classIndex;
+ if ((classIndex = classCache.get(declaringClass)) < 0) {
// The entry doesn't exit yet
- nameIndex = literalIndex(aTypeBinding.constantPoolName());
- index = classCache.put(aTypeBinding, currentIndex++);
+ int nameIndex = literalIndex(declaringClass);
+ classIndex = classCache.put(declaringClass, this.currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
@@ -1051,1979 +640,236 @@ public int literalIndex(TypeBinding aTypeBinding) {
// Then add the 8 bytes representing the long
writeU2(nameIndex);
}
- } else {
- if ((index = wellKnownTypes[indexWellKnownType]) == 0) {
- // Need to insert that binding
- nameIndex = literalIndex(aTypeBinding.constantPoolName());
- index = wellKnownTypes[indexWellKnownType] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
+ int nameAndTypeIndex = literalIndexForMethod(selector, signature);
+ index = putInCache(declaringClass, selector, signature, currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
+ // Write the interface method ref constant into the constant pool
+ // First add the tag
+ writeU1(isInterface ? InterfaceMethodRefTag : MethodRefTag);
+ // Then write the class index
+ writeU2(classIndex);
+ // The write the nameAndType index
+ writeU2(nameAndTypeIndex);
}
return index;
}
-/**
- * This method returns the index into the constantPool corresponding
- * nameAndType constant with nameIndex, typeIndex.
- *
- * @param nameIndex int
- * @param typeIndex int
- * @param key org.eclipse.jdt.internal.compiler.lookup.FieldBinding
- * @return int
- */
-public int literalIndexForFields(int nameIndex, int typeIndex, FieldBinding key) {
- int index;
- int indexOfWellKnownFieldNameAndType;
- if ((indexOfWellKnownFieldNameAndType = indexOfWellKnownFieldNameAndType(key)) == -1) {
- // check if the entry already exists
- if ((index = nameAndTypeCacheForFields.get(key)) == -1) {
- // The entry doesn't exit yet
- index = nameAndTypeCacheForFields.put(key, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- } else {
- if ((index = wellKnownFieldNameAndTypes[indexOfWellKnownFieldNameAndType]) == 0) {
- index = wellKnownFieldNameAndTypes[indexOfWellKnownFieldNameAndType] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
+private int literalIndexForField(char[] name, char[] signature) {
+ int index = getFromNameAndTypeCache(name, signature);
+ if (index == -1) {
+ // The entry doesn't exit yet
+ int nameIndex = literalIndex(name);
+ int typeIndex = literalIndex(signature);
+ index = putInNameAndTypeCache(name, signature, currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
+ writeU1(NameAndTypeTag);
+ writeU2(nameIndex);
+ writeU2(typeIndex);
}
return index;
}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangBoolean() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_BOOLEAN_TYPE]) == 0) {
- int nameIndex;
+public int literalIndexForMethod(char[] selector, char[] signature) {
+ int index = getFromNameAndTypeCache(selector, signature);
+ if (index == -1) {
// The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangBooleanConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_BOOLEAN_TYPE] = currentIndex++;
+ int nameIndex = literalIndex(selector);
+ int typeIndex = literalIndex(signature);
+ index = putInNameAndTypeCache(selector, signature, currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
+ writeU1(NameAndTypeTag);
writeU2(nameIndex);
+ writeU2(typeIndex);
}
return index;
}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangBooleanTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_BOOLEAN_FIELD]) == 0) {
- int nameAndTypeIndex;
+public int literalIndexForField(char[] declaringClass, char[] name, char[] signature) {
+ int index = getFromCache(declaringClass, name, signature);
+ if (index == -1) {
int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangBoolean();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
+ if ((classIndex = classCache.get(declaringClass)) < 0) {
+ // The entry doesn't exit yet
+ int nameIndex = literalIndex(declaringClass);
+ classIndex = classCache.put(declaringClass, this.currentIndex++);
+ if (index > 0xFFFF){
+ this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+ }
+ writeU1(ClassTag);
+ // Then add the 8 bytes representing the long
writeU2(nameIndex);
- writeU2(typeIndex);
}
- index = wellKnownFields[TYPE_BOOLEAN_FIELD] = currentIndex++;
+ int nameAndTypeIndex = literalIndexForField(name, signature);
+ index = putInCache(declaringClass, name, signature, currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
+ // Write the interface method ref constant into the constant pool
+ // First add the tag
writeU1(FieldRefTag);
+ // Then write the class index
writeU2(classIndex);
- writeU2(nameAndTypeIndex);
+ // The write the nameAndType index
+ writeU2(nameAndTypeIndex);
}
return index;
}
/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
+ * This method returns the index into the constantPool corresponding
+ * nameAndType constant with nameIndex, typeIndex.
*
- * @return int
+ * @param nameIndex the given name index
+ * @param typeIndex the given type index
+ * @param name the given field name
+ * @param signature the given field signature
+ * @return the index into the constantPool corresponding
+ * nameAndType constant with nameIndex, typeInde
*/
-public int literalIndexForJavaLangByte() {
+private int literalIndexForFields(int nameIndex, int typeIndex, char[] name, char[] signature) {
int index;
- if ((index = wellKnownTypes[JAVA_LANG_BYTE_TYPE]) == 0) {
- int nameIndex;
+ if ((index = getFromNameAndTypeCache(name, signature)) == -1) {
// The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangByteConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_BYTE_TYPE] = currentIndex++;
+ index = putInNameAndTypeCache(name, signature, currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
+ writeU1(NameAndTypeTag);
writeU2(nameIndex);
+ writeU2(typeIndex);
}
return index;
}
/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
+ * This method returns the index into the constantPool corresponding to the type descriptor.
*
+ * @param stringCharArray char[]
* @return int
*/
-public int literalIndexForJavaLangByteTYPE() {
+public int literalIndexForLdc(char[] stringCharArray) {
int index;
- if ((index = wellKnownFields[TYPE_BYTE_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
+ if ((index = stringCache.get(stringCharArray)) < 0) {
+ int stringIndex;
// The entry doesn't exit yet
- classIndex = literalIndexForJavaLangByte();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
+ if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
+ // The entry doesn't exit yet
+ // Write the tag first
+ writeU1(Utf8Tag);
+ // Then the size of the stringName array
+ int savedCurrentOffset = currentOffset;
+ if (currentOffset + 2 >= poolContent.length) {
+ // we need to resize the poolContent array because we won't have
+ // enough space to write the length
+ resizePoolContents(2);
+ }
+ currentOffset += 2;
+ int length = 0;
+ for (int i = 0; i < stringCharArray.length; i++) {
+ char current = stringCharArray[i];
+ if ((current >= 0x0001) && (current <= 0x007F)) {
+ // we only need one byte: ASCII table
+ writeU1(current);
+ length++;
+ } else
+ if (current > 0x07FF) {
+ // we need 3 bytes
+ length += 3;
+ writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
+ writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
+ writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+ } else {
+ // we can be 0 or between 0x0080 and 0x07FF
+ // In that case we only need 2 bytes
+ length += 2;
+ writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
+ writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+ }
+ }
+ if (length >= 65535) {
+ currentOffset = savedCurrentOffset - 1;
+ return -1;
+ }
+ stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
+ // Now we know the length that we have to write in the constant pool
+ // we use savedCurrentOffset to do that
+ if (length > 65535) {
+ return 0;
+ }
+ poolContent[savedCurrentOffset] = (byte) (length >> 8);
+ poolContent[savedCurrentOffset + 1] = (byte) length;
}
- index = wellKnownFields[TYPE_BYTE_FIELD] = currentIndex++;
+ index = stringCache.put(stringCharArray, currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
+ // Write the tag first
+ writeU1(StringTag);
+ // Then the string index
+ writeU2(stringIndex);
}
return index;
}
/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
+ * This method returns the index into the constantPool corresponding
+ * nameAndType constant with nameIndex, typeIndex.
*
+ * @param nameIndex the given name index
+ * @param typeIndex the given type index
+ * @param selector the given method selector
+ * @param signature the given method signature
* @return int
*/
-public int literalIndexForJavaLangCharacter() {
+public int literalIndexForMethods(int nameIndex, int typeIndex, char[] selector, char[] signature) {
int index;
- if ((index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE]) == 0) {
- int nameIndex;
+ if ((index = getFromNameAndTypeCache(selector, signature)) == -1) {
// The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangCharacterConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE] = currentIndex++;
+ index = putInNameAndTypeCache(selector, signature, currentIndex++);
if (index > 0xFFFF){
this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
}
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
+ writeU1(NameAndTypeTag);
writeU2(nameIndex);
+ writeU2(typeIndex);
+ }
+ return index;
+}
+private int putInNameAndTypeCache(final char[] key1, final char[] key2, int index) {
+ CharArrayCache value = (CharArrayCache) this.nameAndTypeCacheForFieldsAndMethods.get(key1);
+ if (value == null) {
+ CharArrayCache charArrayCache = new CharArrayCache();
+ charArrayCache.put(key2, index);
+ this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache);
+ } else {
+ value.put(key2, index);
}
return index;
}
/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
+ * @param key1
+ * @param key2
+ * @param key3
+ * @param index
+ * @return the given index
*/
-public int literalIndexForJavaLangCharacterTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_CHARACTER_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangCharacter();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
+private int putInCache(final char[] key1, final char[] key2, final char[] key3, int index) {
+ HashtableOfObject value = (HashtableOfObject) this.methodsAndFieldsCache.get(key1);
+ if (value == null) {
+ value = new HashtableOfObject();
+ this.methodsAndFieldsCache.put(key1, value);
+ CharArrayCache charArrayCache = new CharArrayCache();
+ charArrayCache.put(key3, index);
+ value.put(key2, charArrayCache);
+ } else {
+ CharArrayCache charArrayCache = (CharArrayCache) value.get(key2);
+ if (charArrayCache == null) {
+ charArrayCache = new CharArrayCache();
+ charArrayCache.put(key3, index);
+ value.put(key2, charArrayCache);
+ } else {
+ charArrayCache.put(key3, index);
}
- index = wellKnownFields[TYPE_CHARACTER_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangClass() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_CLASS_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_CLASS_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangClassForName() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[FORNAME_CLASS_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangClass();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ForName);
- int typeIndex = literalIndex(QualifiedNamesConstants.ForNameSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[FORNAME_CLASS_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangClassDesiredAssertionStatus() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangClass();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatus);
- int typeIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatusSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangClassGetComponentType() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangClass();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.GetComponentType);
- int typeIndex = literalIndex(QualifiedNamesConstants.GetComponentTypeSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangClassNotFoundException() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassNotFoundExceptionConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangDouble() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangDoubleConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangDoubleTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_DOUBLE_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangDouble();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_DOUBLE_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangError() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_ERROR_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangErrorConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_ERROR_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangErrorConstructor() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-public int literalIndexForJavaLangException() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE]) == 0) {
- // The entry doesn't exit yet
- int nameIndex = literalIndex(QualifiedNamesConstants.JavaLangExceptionConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangFloat() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangFloatConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangFloatTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_FLOAT_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangFloat();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_FLOAT_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangInteger() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangIntegerConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangIntegerTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_INTEGER_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangInteger();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_INTEGER_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangLong() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_LONG_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangLongConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_LONG_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangLongTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_LONG_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangLong();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_LONG_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangNoClassDefFoundError() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangNoClassDefFoundErrorConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangAssertionError() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangAssertionErrorConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param typeBindingID int
- * @return int
- */
-public int literalIndexForJavaLangAssertionErrorConstructor(int typeBindingID) {
- int index = 0;
- int nameAndTypeIndex = 0;
- int classIndex = 0;
- switch (typeBindingID) {
- case T_int :
- case T_byte :
- case T_short :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorIntConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_long :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorLongConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_float :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorFloatConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_double :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorDoubleConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_char :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorCharConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_boolean :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorBooleanConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- //case T_Object :
- //case T_String :
- //case T_null :
- default :
- if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorObjectConstrSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- }
- return index;
-}
-
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangAssertionErrorDefaultConstructor() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangAssertionError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-
-
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangNoClassDefFoundErrorStringConstructor() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangNoClassDefFoundError();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangObject() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangObjectConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangReflectConstructor() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangReflectConstructor);
- index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-public int literalIndexForJavaLangReflectConstructorNewInstance() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangReflectConstructor();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.NewInstance);
- int typeIndex = literalIndex(QualifiedNamesConstants.NewInstanceSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangShort() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_SHORT_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangShortConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_SHORT_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangShortTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_SHORT_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangShort();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_SHORT_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangString() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_STRING_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_STRING_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringBuffer() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringBufferConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringBufferAppend(int typeID) {
- int index = 0;
- int nameAndTypeIndex = 0;
- int classIndex = 0;
- switch (typeID) {
- case T_int :
- case T_byte :
- case T_short :
- if ((index = wellKnownMethods[APPEND_INT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendIntSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_INT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_long :
- if ((index = wellKnownMethods[APPEND_LONG_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendLongSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_LONG_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_float :
- if ((index = wellKnownMethods[APPEND_FLOAT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendFloatSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_FLOAT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_double :
- if ((index = wellKnownMethods[APPEND_DOUBLE_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendDoubleSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_DOUBLE_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_char :
- if ((index = wellKnownMethods[APPEND_CHAR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendCharSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_CHAR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_boolean :
- if ((index = wellKnownMethods[APPEND_BOOLEAN_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendBooleanSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_BOOLEAN_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_Object :
- if ((index = wellKnownMethods[APPEND_OBJECT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendObjectSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_OBJECT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_String :
- case T_null :
- if ((index = wellKnownMethods[APPEND_STRING_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Append);
- int typeIndex = literalIndex(QualifiedNamesConstants.AppendStringSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[APPEND_STRING_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringBufferConstructor() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringBufferDefaultConstructor() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Init);
- int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringBufferToString() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangStringBuffer();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ToString);
- int typeIndex = literalIndex(QualifiedNamesConstants.ToStringSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringIntern() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[STRING_INTERN_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangString();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Intern);
- int typeIndex = literalIndex(QualifiedNamesConstants.InternSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[STRING_INTERN_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangStringValueOf(int typeID) {
- int index = 0;
- int nameAndTypeIndex = 0;
- int classIndex = literalIndexForJavaLangString();
- switch (typeID) {
- case T_int :
- case T_byte :
- case T_short :
- if ((index = wellKnownMethods[VALUEOF_INT_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfIntSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_INT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_long :
- if ((index = wellKnownMethods[VALUEOF_LONG_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfLongSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_LONG_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_float :
- if ((index = wellKnownMethods[VALUEOF_FLOAT_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfFloatSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_FLOAT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_double :
- if ((index = wellKnownMethods[VALUEOF_DOUBLE_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfDoubleSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_DOUBLE_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_char :
- if ((index = wellKnownMethods[VALUEOF_CHAR_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfCharSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_CHAR_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_boolean :
- if ((index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfBooleanSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- case T_Object :
- if ((index = wellKnownMethods[VALUEOF_OBJECT_METHOD]) == 0) {
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
- int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfObjectSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[VALUEOF_OBJECT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- break;
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangSystem() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangSystemConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangSystemExitInt() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[SYSTEM_EXIT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangSystem();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Exit);
- int typeIndex = literalIndex(QualifiedNamesConstants.ExitIntSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[SYSTEM_EXIT_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangSystemOut() {
- int index;
- if ((index = wellKnownFields[OUT_SYSTEM_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangSystem();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.Out);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaIoPrintStreamSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[OUT_SYSTEM_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangThrowable() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangThrowableConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangThrowableGetMessage() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangThrowable();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.GetMessage);
- int typeIndex = literalIndex(QualifiedNamesConstants.GetMessageSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @return int
- */
-public int literalIndexForJavaLangVoid() {
- int index;
- if ((index = wellKnownTypes[JAVA_LANG_VOID_TYPE]) == 0) {
- int nameIndex;
- // The entry doesn't exit yet
- nameIndex = literalIndex(QualifiedNamesConstants.JavaLangVoidConstantPoolName);
- index = wellKnownTypes[JAVA_LANG_VOID_TYPE] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(ClassTag);
- // Then add the 8 bytes representing the long
- writeU2(nameIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool
- * corresponding to the field binding aFieldBinding.
- *
- * @return int
- */
-public int literalIndexForJavaLangVoidTYPE() {
- int index;
- if ((index = wellKnownFields[TYPE_VOID_FIELD]) == 0) {
- int nameAndTypeIndex;
- int classIndex;
- // The entry doesn't exit yet
- classIndex = literalIndexForJavaLangVoid();
- if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
- int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
- nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownFields[TYPE_VOID_FIELD] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(FieldRefTag);
- writeU2(classIndex);
- writeU2(nameAndTypeIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the type descriptor.
- *
- * @param stringCharArray char[]
- * @return int
- */
-public int literalIndexForLdc(char[] stringCharArray) {
- int index;
- if ((index = stringCache.get(stringCharArray)) < 0) {
- int stringIndex;
- // The entry doesn't exit yet
- if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
- // The entry doesn't exit yet
- // Write the tag first
- writeU1(Utf8Tag);
- // Then the size of the stringName array
- int savedCurrentOffset = currentOffset;
- if (currentOffset + 2 >= poolContent.length) {
- // we need to resize the poolContent array because we won't have
- // enough space to write the length
- resizePoolContents(2);
- }
- currentOffset += 2;
- int length = 0;
- for (int i = 0; i < stringCharArray.length; i++) {
- char current = stringCharArray[i];
- if ((current >= 0x0001) && (current <= 0x007F)) {
- // we only need one byte: ASCII table
- writeU1(current);
- length++;
- } else
- if (current > 0x07FF) {
- // we need 3 bytes
- length += 3;
- writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
- writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
- writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
- } else {
- // we can be 0 or between 0x0080 and 0x07FF
- // In that case we only need 2 bytes
- length += 2;
- writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
- writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
- }
- }
- if (length >= 65535) {
- currentOffset = savedCurrentOffset - 1;
- return -1;
- }
- stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
- // Now we know the length that we have to write in the constant pool
- // we use savedCurrentOffset to do that
- if (length > 65535) {
- return 0;
- }
- poolContent[savedCurrentOffset] = (byte) (length >> 8);
- poolContent[savedCurrentOffset + 1] = (byte) length;
- }
- index = stringCache.put(stringCharArray, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- // Write the tag first
- writeU1(StringTag);
- // Then the string index
- writeU2(stringIndex);
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding
- * nameAndType constant with nameIndex, typeIndex.
- *
- * @param nameIndex int
- * @param typeIndex int
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int literalIndexForMethods(int nameIndex, int typeIndex, MethodBinding key) {
- int index;
- int indexOfWellKnownMethodNameAndType;
- if ((indexOfWellKnownMethodNameAndType = indexOfWellKnownMethodNameAndType(key)) == -1) {
- // check if the entry exists
- if ((index = nameAndTypeCacheForMethods.get(key)) == -1) {
- // The entry doesn't exit yet
- index = nameAndTypeCacheForMethods.put(key, currentIndex++);
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- } else {
- if ((index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType]) == 0) {
- index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType] = currentIndex++;
- if (index > 0xFFFF){
- this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
- }
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- }
- return index;
-}
-/**
- * This method returns the index into the constantPool corresponding to the
- * method descriptor. It can be either an interface method reference constant
- * or a method reference constant.
- *
- * @return int
- */
-public int literalIndexForJavaLangObjectGetClass() {
- int index;
- int nameAndTypeIndex;
- int classIndex;
- // Looking into the method ref table
- if ((index = wellKnownMethods[GETCLASS_OBJECT_METHOD]) == 0) {
- classIndex = literalIndexForJavaLangObject();
- if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCLASS_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
- int nameIndex = literalIndex(QualifiedNamesConstants.GetClass);
- int typeIndex = literalIndex(QualifiedNamesConstants.GetClassSignature);
- nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCLASS_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
- writeU1(NameAndTypeTag);
- writeU2(nameIndex);
- writeU2(typeIndex);
- }
- index = wellKnownMethods[GETCLASS_OBJECT_METHOD] = currentIndex++;
- // Write the method ref constant into the constant pool
- // First add the tag
- writeU1(MethodRefTag);
- // Then write the class index
- writeU2(classIndex);
- // The write the nameAndType index
- writeU2(nameAndTypeIndex);
}
return index;
}
@@ -3039,11 +885,11 @@ public void resetForClinit(int constantPoolIndex, int constantPoolOffset) {
if (UTF8Cache.get(AttributeNamesConstants.CodeName) >= constantPoolIndex) {
UTF8Cache.remove(AttributeNamesConstants.CodeName);
}
- if (UTF8Cache.get(QualifiedNamesConstants.ClinitSignature) >= constantPoolIndex) {
- UTF8Cache.remove(QualifiedNamesConstants.ClinitSignature);
+ if (UTF8Cache.get(ConstantPool.ClinitSignature) >= constantPoolIndex) {
+ UTF8Cache.remove(ConstantPool.ClinitSignature);
}
- if (UTF8Cache.get(QualifiedNamesConstants.Clinit) >= constantPoolIndex) {
- UTF8Cache.remove(QualifiedNamesConstants.Clinit);
+ if (UTF8Cache.get(ConstantPool.Clinit) >= constantPoolIndex) {
+ UTF8Cache.remove(ConstantPool.Clinit);
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java b/src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java
deleted file mode 100644
index 0982a06..0000000
--- a/src/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.codegen;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-
-public class FieldNameAndTypeCache {
- public FieldBinding keyTable[];
- public int valueTable[];
- int elementSize;
- int threshold;
-/**
- * Constructs a new, empty hashtable. A default capacity is used.
- * Note that the hashtable will automatically grow when it gets full.
- */
-public FieldNameAndTypeCache() {
- this(13);
-}
-/**
- * Constructs a new, empty hashtable with the specified initial
- * capacity.
- * @param initialCapacity int
- * the initial number of buckets
- */
-public FieldNameAndTypeCache(int initialCapacity) {
- this.elementSize = 0;
- this.threshold = (int) (initialCapacity * 0.66f);
- this.keyTable = new FieldBinding[initialCapacity];
- this.valueTable = new int[initialCapacity];
-}
-/**
- * Clears the hash table so that it has no more elements in it.
- */
-public void clear() {
- for (int i = keyTable.length; --i >= 0;) {
- keyTable[i] = null;
- valueTable[i] = 0;
- }
- elementSize = 0;
-}
-/** Returns true if the collection contains an element for the key.
- *
- * @param key char[] the key that we are looking for
- * @return boolean
- */
-public boolean containsKey(FieldBinding key) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return true;
- index = (index + 1) % keyTable.length;
- }
- return false;
-}
-/**
- * Return true if the two field binding are consider like equals.
- */
-public boolean equalsForNameAndType(FieldBinding field1, FieldBinding field2) {
- return ((field1.type == field2.type) && CharOperation.equals(field1.name, field2.name));
-}
-/** Gets the object associated with the specified key in the
- * hashtable.
- * @param key char[]
the specified key
- * @return int the element for the key or -1 if the key is not
- * defined in the hash table.
- */
-public int get(FieldBinding key) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return valueTable[index];
- index = (index + 1) % keyTable.length;
- }
- return -1;
-}
-/**
- * Return the hashcode for the key parameter
- *
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int hashCode(FieldBinding key) {
- return ((CharOperation.hashCode(key.name) + key.type.hashCode()) & 0x7FFFFFFF) % keyTable.length;
-}
-/**
- * Puts the specified element into the hashtable, using the specified
- * key. The element may be retrieved by doing a get() with the same key.
- * The key and the element cannot be null.
- *
- * @param key Object
the specified key in the hashtable
- * @param value int
the specified element
- * @return int the old value of the key, or -1 if it did not have one.
- */
-public int put(FieldBinding key, int value) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return valueTable[index] = value;
- index = (index + 1) % keyTable.length;
- }
- keyTable[index] = key;
- valueTable[index] = value;
-
- // assumes the threshold is never equal to the size of the table
- if (++elementSize > threshold)
- rehash();
- return value;
-}
-/**
- * Rehashes the content of the table into a bigger table.
- * This method is called automatically when the hashtable's
- * size exceeds the threshold.
- */
-private void rehash() {
- FieldNameAndTypeCache newHashtable = new FieldNameAndTypeCache(keyTable.length * 2);
- for (int i = keyTable.length; --i >= 0;)
- if (keyTable[i] != null)
- newHashtable.put(keyTable[i], valueTable[i]);
-
- this.keyTable = newHashtable.keyTable;
- this.valueTable = newHashtable.valueTable;
- this.threshold = newHashtable.threshold;
-}
-/**
- * Returns the number of elements contained in the hashtable.
- *
- * @return int
The size of the table
- */
-public int size() {
- return elementSize;
-}
-/**
- * Converts to a rather lengthy String.
- *
- * @return String the ascii representation of the receiver
- */
-public String toString() {
- int max = size();
- StringBuffer buf = new StringBuffer();
- buf.append("{"); //$NON-NLS-1$
- for (int i = 0; i < max; ++i) {
- if (keyTable[i] != null) {
- buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
- }
- if (i < max) {
- buf.append(", "); //$NON-NLS-1$
- }
- }
- buf.append("}"); //$NON-NLS-1$
- return buf.toString();
-}
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java b/src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java
deleted file mode 100644
index 2ab3da3..0000000
--- a/src/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.codegen;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-
-public class MethodNameAndTypeCache {
- public MethodBinding keyTable[];
- public int valueTable[];
- int elementSize;
- int threshold;
-/**
- * Constructs a new, empty hashtable. A default capacity is used.
- * Note that the hashtable will automatically grow when it gets full.
- */
-public MethodNameAndTypeCache() {
- this(13);
-}
-/**
- * Constructs a new, empty hashtable with the specified initial
- * capacity.
- * @param initialCapacity int
- * the initial number of buckets
- */
-public MethodNameAndTypeCache(int initialCapacity) {
- this.elementSize = 0;
- this.threshold = (int) (initialCapacity * 0.66f);
- this.keyTable = new MethodBinding[initialCapacity];
- this.valueTable = new int[initialCapacity];
-}
-/**
- * Clears the hash table so that it has no more elements in it.
- */
-public void clear() {
- for (int i = keyTable.length; --i >= 0;) {
- keyTable[i] = null;
- valueTable[i] = 0;
- }
- elementSize = 0;
-}
-/** Returns true if the collection contains an element for the key.
- *
- * @param key char[] the key that we are looking for
- * @return boolean
- */
-public boolean containsKey(MethodBinding key) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return true;
- index = (index + 1) % keyTable.length;
- }
- return false;
-}
-/**
- * Returns true if the two methodBinding are consider to be equal for the name and type
- * purpose
- */
-public boolean equalsForNameAndType(MethodBinding method1, MethodBinding method2) {
- return CharOperation.equals(method1.selector, method2.selector) && CharOperation.equals(method1.signature(), method2.signature());
-}
-/** Gets the object associated with the specified key in the
- * hashtable.
- * @param key char[]
the specified key
- * @return int the element for the key or -1 if the key is not
- * defined in the hash table.
- */
-public int get(MethodBinding key) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return valueTable[index];
- index = (index + 1) % keyTable.length;
- }
- return -1;
-}
-/**
- * Return the hashcode for the key parameter
- *
- * @param key org.eclipse.jdt.internal.compiler.lookup.MethodBinding
- * @return int
- */
-public int hashCode(MethodBinding key) {
- return CharOperation.hashCode(key.selector) % keyTable.length;
-}
-/**
- * Puts the specified element into the hashtable, using the specified
- * key. The element may be retrieved by doing a get() with the same key.
- * The key and the element cannot be null.
- *
- * @param key Object
the specified key in the hashtable
- * @param value int
the specified element
- * @return int the old value of the key, or -1 if it did not have one.
- */
-public int put(MethodBinding key, int value) {
- int index = hashCode(key);
- while (keyTable[index] != null) {
- if (equalsForNameAndType(keyTable[index], key))
- return valueTable[index] = value;
- index = (index + 1) % keyTable.length;
- }
- keyTable[index] = key;
- valueTable[index] = value;
-
- // assumes the threshold is never equal to the size of the table
- if (++elementSize > threshold)
- rehash();
- return value;
-}
-/**
- * Rehashes the content of the table into a bigger table.
- * This method is called automatically when the hashtable's
- * size exceeds the threshold.
- */
-private void rehash() {
- MethodNameAndTypeCache newHashtable = new MethodNameAndTypeCache(keyTable.length * 2);
- for (int i = keyTable.length; --i >= 0;)
- if (keyTable[i] != null)
- newHashtable.put(keyTable[i], valueTable[i]);
-
- this.keyTable = newHashtable.keyTable;
- this.valueTable = newHashtable.valueTable;
- this.threshold = newHashtable.threshold;
-}
-/**
- * Returns the number of elements contained in the hashtable.
- *
- * @return int
The size of the table
- */
-public int size() {
- return elementSize;
-}
-/**
- * Converts to a rather lengthy String.
- *
- * @return String the ascii representation of the receiver
- */
-public String toString() {
- int max = size();
- StringBuffer buf = new StringBuffer();
- buf.append("{"); //$NON-NLS-1$
- for (int i = 0; i < max; ++i) {
- if (keyTable[i] != null) {
- buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
- }
- if (i < max) {
- buf.append(", "); //$NON-NLS-1$
- }
- }
- buf.append("}"); //$NON-NLS-1$
- return buf.toString();
-}
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java b/src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
deleted file mode 100644
index aff4cb8..0000000
--- a/src/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.codegen;
-
-public interface QualifiedNamesConstants {
- char[] JavaLangObjectConstantPoolName = "java/lang/Object".toCharArray(); //$NON-NLS-1$
- char[] JavaLangStringConstantPoolName = "java/lang/String".toCharArray(); //$NON-NLS-1$
- char[] JavaLangStringBufferConstantPoolName = "java/lang/StringBuffer".toCharArray(); //$NON-NLS-1$
- char[] JavaLangClassConstantPoolName = "java/lang/Class".toCharArray(); //$NON-NLS-1$
- char[] JavaLangThrowableConstantPoolName = "java/lang/Throwable".toCharArray(); //$NON-NLS-1$
- char[] JavaLangClassNotFoundExceptionConstantPoolName = "java/lang/ClassNotFoundException".toCharArray(); //$NON-NLS-1$
- char[] JavaLangNoClassDefFoundErrorConstantPoolName = "java/lang/NoClassDefFoundError".toCharArray(); //$NON-NLS-1$
- char[] JavaLangIntegerConstantPoolName = "java/lang/Integer".toCharArray(); //$NON-NLS-1$
- char[] JavaLangFloatConstantPoolName = "java/lang/Float".toCharArray(); //$NON-NLS-1$
- char[] JavaLangDoubleConstantPoolName = "java/lang/Double".toCharArray(); //$NON-NLS-1$
- char[] JavaLangLongConstantPoolName = "java/lang/Long".toCharArray(); //$NON-NLS-1$
- char[] JavaLangShortConstantPoolName = "java/lang/Short".toCharArray(); //$NON-NLS-1$
- char[] JavaLangByteConstantPoolName = "java/lang/Byte".toCharArray(); //$NON-NLS-1$
- char[] JavaLangCharacterConstantPoolName = "java/lang/Character".toCharArray(); //$NON-NLS-1$
- char[] JavaLangVoidConstantPoolName = "java/lang/Void".toCharArray(); //$NON-NLS-1$
- char[] JavaLangBooleanConstantPoolName = "java/lang/Boolean".toCharArray(); //$NON-NLS-1$
- char[] JavaLangSystemConstantPoolName = "java/lang/System".toCharArray(); //$NON-NLS-1$
- char[] JavaLangErrorConstantPoolName = "java/lang/Error".toCharArray(); //$NON-NLS-1$
- char[] JavaLangExceptionConstantPoolName = "java/lang/Exception".toCharArray(); //$NON-NLS-1$
- char[] JavaLangReflectConstructor = "java/lang/reflect/Constructor".toCharArray(); //$NON-NLS-1$
- char[] Append = new char[] {'a', 'p', 'p', 'e', 'n', 'd'};
- char[] ToString = new char[] {'t', 'o', 'S', 't', 'r', 'i', 'n', 'g'};
- char[] Init = new char[] {'<', 'i', 'n', 'i', 't', '>'};
- char[] Clinit = new char[] {'<', 'c', 'l', 'i', 'n', 'i', 't', '>'};
- char[] ValueOf = new char[] {'v', 'a', 'l', 'u', 'e', 'O', 'f'};
- char[] ForName = new char[] {'f', 'o', 'r', 'N', 'a', 'm', 'e'};
- char[] GetMessage = new char[] {'g', 'e', 't', 'M', 'e', 's', 's', 'a', 'g', 'e'};
- char[] NewInstance = "newInstance".toCharArray(); //$NON-NLS-1$
- char[] GetConstructor = "getConstructor".toCharArray(); //$NON-NLS-1$
- char[] Exit = new char[] {'e', 'x', 'i', 't'};
- char[] Intern = "intern".toCharArray(); //$NON-NLS-1$
- char[] Out = new char[] {'o', 'u', 't'};
- char[] TYPE = new char[] {'T', 'Y', 'P', 'E'};
- char[] This = new char[] {'t', 'h', 'i', 's'};
- char[] JavaLangClassSignature = new char[] {'L', 'j', 'a', 'v', 'a', '/', 'l', 'a', 'n', 'g', '/', 'C', 'l', 'a', 's', 's', ';'};
- char[] ForNameSignature = "(Ljava/lang/String;)Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
- char[] GetMessageSignature = "()Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] GetConstructorSignature = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
- char[] StringConstructorSignature = "(Ljava/lang/String;)V".toCharArray(); //$NON-NLS-1$
- char[] NewInstanceSignature = "([Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
- char[] DefaultConstructorSignature = {'(', ')', 'V'};
- char[] ClinitSignature = DefaultConstructorSignature;
- char[] ToStringSignature = GetMessageSignature;
- char[] InternSignature = GetMessageSignature;
- char[] AppendIntSignature = "(I)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendLongSignature = "(J)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendFloatSignature = "(F)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendDoubleSignature = "(D)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendCharSignature = "(C)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendBooleanSignature = "(Z)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendObjectSignature = "(Ljava/lang/Object;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] AppendStringSignature = "(Ljava/lang/String;)Ljava/lang/StringBuffer;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfObjectSignature = "(Ljava/lang/Object;)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfIntSignature = "(I)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfLongSignature = "(J)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfCharSignature = "(C)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfBooleanSignature = "(Z)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfDoubleSignature = "(D)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] ValueOfFloatSignature = "(F)Ljava/lang/String;".toCharArray(); //$NON-NLS-1$
- char[] JavaIoPrintStreamSignature = "Ljava/io/PrintStream;".toCharArray(); //$NON-NLS-1$
- char[] ExitIntSignature = new char[] {'(', 'I', ')', 'V'};
- char[] ArrayJavaLangObjectConstantPoolName = "[Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
- char[] ArrayJavaLangClassConstantPoolName = "[Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
- char[] JavaLangAssertionErrorConstantPoolName = "java/lang/AssertionError".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorIntConstrSignature = "(I)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorLongConstrSignature = "(J)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorFloatConstrSignature = "(F)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorDoubleConstrSignature = "(D)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorCharConstrSignature = "(C)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorBooleanConstrSignature = "(Z)V".toCharArray(); //$NON-NLS-1$
- char[] AssertionErrorObjectConstrSignature = "(Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
- char[] DesiredAssertionStatus = "desiredAssertionStatus".toCharArray(); //$NON-NLS-1$
- char[] DesiredAssertionStatusSignature = "()Z".toCharArray(); //$NON-NLS-1$
- char[] ShortConstrSignature = "(S)V".toCharArray(); //$NON-NLS-1$
- char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
- char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
- char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
- char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
- char[] GetComponentTypeSignature = GetClassSignature;
-}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java b/src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java
new file mode 100644
index 0000000..1ed5061
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/env/AccessRestriction.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Definition of an access restriction rule used to flag forbidden references to non API code.
+ * A restriction can chain to further ones, the first violated restriction taking precedence.
+ */
+public class AccessRestriction {
+
+ private char[][] inclusionPatterns;
+ private char[][] exclusionPatterns;
+ protected String messageTemplate;
+ AccessRestriction furtherRestriction; // subsequent restriction
+
+
+ public AccessRestriction(String messageTemplate, char[][] inclusionPatterns, char[][] exclusionPatterns, AccessRestriction furtherRestriction) {
+ this.messageTemplate = messageTemplate;
+ this.inclusionPatterns = inclusionPatterns;
+ this.exclusionPatterns = exclusionPatterns;
+ this.furtherRestriction = furtherRestriction;
+ }
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object object) {
+ if (this == object)
+ return true;
+ if (!(object instanceof AccessRestriction))
+ return false;
+ AccessRestriction otherRestriction = (AccessRestriction) object;
+ if (!this.messageTemplate.equals(otherRestriction.messageTemplate))
+ return false;
+ if (this.inclusionPatterns != otherRestriction.inclusionPatterns) {
+ int length = this.inclusionPatterns == null ? 0 : this.inclusionPatterns.length;
+ int otherLength = otherRestriction.inclusionPatterns == null ? 0 : otherRestriction.inclusionPatterns.length;
+ if (length != otherLength)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!CharOperation.equals(this.inclusionPatterns[i], otherRestriction.inclusionPatterns[i]))
+ return false;
+ }
+ }
+ if (this.exclusionPatterns != otherRestriction.exclusionPatterns) {
+ int length = this.exclusionPatterns == null ? 0 : this.exclusionPatterns.length;
+ int otherLength = otherRestriction.exclusionPatterns == null ? 0 : otherRestriction.exclusionPatterns.length;
+ if (length != otherLength)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!CharOperation.equals(this.exclusionPatterns[i], otherRestriction.exclusionPatterns[i]))
+ return false;
+ }
+ }
+ if (this.furtherRestriction != otherRestriction.furtherRestriction) {
+ if (this.furtherRestriction == null || otherRestriction.furtherRestriction == null)
+ return false;
+ if (!this.furtherRestriction.equals(otherRestriction.furtherRestriction))
+ return false;
+ }
+ return true;
+ }
+ /**
+ * Select the first restriction which is violated when accessing a given type, or null if no restriction applies.
+ * Type name is formed as: "java/lang/Object".
+ */
+ public AccessRestriction getViolatedRestriction(char[] targetTypeName, char[] referringTypeName) {
+
+ // check local inclusion/exclusion rules
+ if (this.inclusionPatterns != null || this.exclusionPatterns != null) {
+ if (Util.isExcluded(targetTypeName, this.inclusionPatterns, this.exclusionPatterns, false)) {
+ return this;
+ }
+ }
+ // then check further restrictions
+ return this.furtherRestriction != null
+ ? this.furtherRestriction.getViolatedRestriction(targetTypeName, referringTypeName)
+ : null;
+ }
+ public char[][] getExclusionPatterns() {
+ return this.exclusionPatterns;
+ }
+ public char[][] getInclusionPatterns() {
+ return this.inclusionPatterns;
+ }
+ /**
+ * Returns readable description for problem reporting,
+ * message is expected to contain room for restricted type name
+ * e.g. "{0} has restricted access"
+ */
+ public String getMessageTemplate() {
+ return this.messageTemplate;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(20);
+ buffer
+ .append("AccessRestriction [includes:\"") //$NON-NLS-1$
+ .append(CharOperation.concatWith(this.inclusionPatterns,'/'))
+ .append("\"][excludes:\"") //$NON-NLS-1$
+ .append(CharOperation.concatWith(this.exclusionPatterns,'/'))
+ .append("\"][template:\"") //$NON-NLS-1$
+ .append(this.messageTemplate)
+ .append("\"]"); //$NON-NLS-1$
+ if (this.furtherRestriction != null) {
+ buffer.append('\n').append(this.furtherRestriction);
+ }
+ return buffer.toString();
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IBinaryField.java b/src/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
index d928f82..28211a1 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
@@ -30,4 +30,14 @@ Constant getConstant();
*/
char[] getTypeName();
+
+/**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec.
+ */
+char[] getGenericSignature();
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java b/src/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
index 75435bc..9f2ecd0 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
@@ -29,7 +29,7 @@ char[][] getExceptionTypeNames();
/**
* Answer the receiver's method descriptor which describes the parameter &
- * return types as specified in section 4.3.3 of the Java 2 VM spec.
+ * return types as specified in section 4.4.3 of the Java 2 VM spec.
*
* For example:
* - int foo(String) is (Ljava/lang/String;)I
@@ -38,6 +38,17 @@ char[][] getExceptionTypeNames();
char[] getMethodDescriptor();
/**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec.
+ */
+char[] getGenericSignature();
+
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
+
+/**
* Answer whether the receiver represents a class initializer method.
*/
boolean isClinit();
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/src/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
index aacda73..f693287 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
@@ -65,6 +65,16 @@ IBinaryMethod[] getMethods();
*/
char[] getName();
+
+/**
+ * Answer the receiver's signature which describes the parameter &
+ * return types as specified in section 4.4.4 of the Java 2 VM spec 3rd edition.
+ * Returns null if none.
+ *
+ * @return the receiver's signature, null if none
+ */
+char[] getGenericSignature();
+
/**
* Answer the resolved name of the receiver's superclass in the
* class file format as specified in section 4.2 of the Java 2 VM spec
@@ -74,7 +84,10 @@ char[] getName();
*/
char[] getSuperclassName();
-
+/**
+ * Answer the tagbits set according to the bits for annotations.
+ */
+long getTagBits();
/**
* Answer true if the receiver is an anonymous class.
* false otherwise
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IConstants.java b/src/org/eclipse/jdt/internal/compiler/env/IConstants.java
index 4f3bfa1..c6cb0ac 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IConstants.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IConstants.java
@@ -10,40 +10,44 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.env;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
/**
- * This interface defines constants for use by the builder / compiler interface.
+ * This interface defines constants for use by the builder / compiler
+ * interface.
*/
public interface IConstants {
-
int AccDefault = 0;
-
- /**
+ /*
* Modifiers
*/
- int AccPublic = 0x0001;
- int AccPrivate = 0x0002;
- int AccProtected = 0x0004;
- int AccStatic = 0x0008;
- int AccFinal = 0x0010;
+ int AccPublic = 0x0001;
+ int AccPrivate = 0x0002;
+ int AccProtected = 0x0004;
+ int AccStatic = 0x0008;
+ int AccFinal = 0x0010;
int AccSynchronized = 0x0020;
- int AccVolatile = 0x0040;
- int AccBridge = 0x0040;
- int AccTransient = 0x0080;
- int AccVarargs = 0x0080;
- int AccNative = 0x0100;
- int AccInterface = 0x0200;
- int AccAbstract = 0x0400;
- int AccStrictfp = 0x0800;
- int AccSynthetic = 0x1000;
+ int AccVolatile = 0x0040;
+ int AccBridge = 0x0040;
+ int AccTransient = 0x0080;
+ int AccVarargs = 0x0080;
+ int AccNative = 0x0100;
+ int AccInterface = 0x0200;
+ int AccAbstract = 0x0400;
+ int AccStrictfp = 0x0800;
+ int AccSynthetic = 0x1000;
+ int AccAnnotation = 0x2000;
+ int AccEnum = 0x4000;
/**
* Other VM flags.
*/
int AccSuper = 0x0020;
-
/**
* Extra flags for types and members attributes.
*/
- int AccDeprecated = 0x100000;
+ int AccAnnotationDefault = ASTNode.Bit18; // indicate presence of an attribute "DefaultValue" (annotation method)
+ int AccDeprecated = ASTNode.Bit21; // indicate presence of an attribute "Deprecated"
+
}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IDependent.java b/src/org/eclipse/jdt/internal/compiler/env/IDependent.java
index bf645ec..91b5b4a 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IDependent.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IDependent.java
@@ -18,15 +18,26 @@ package org.eclipse.jdt.internal.compiler.env;
* when file dependencies are collected.
*/
public interface IDependent {
+ char JAR_FILE_ENTRY_SEPARATOR = '|';
/**
* Answer the file name which defines the type.
*
* The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
+ * file proper name by a separator suitable for the type (java.io.File.separator for example),
+ * e.g.
+ * "c:\\source\\com\\p\\X.java" or
+ * "/com/p/Y.java".
+ *
+ * The path to the zip or jar file (optional) must be separated
+ * from the actual path part by JAR_FILE_ENTRY_SEPARATOR,
+ * e.g.
+ * "c:\\lib\\some.jar|/com/p/X.class" or
+ * "/lib/some.zip|/com/q/Y.class".
*
* The proper file name includes the suffix extension (e.g. ".java")
- *
- * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
+ * e.g. "c:/org/eclipse/jdt/internal/compileri/env/IDependent.java"
+ *
+ * Return null if no file defines the type.
*/
char[] getFileName();
diff --git a/src/org/eclipse/jdt/internal/compiler/env/IGenericType.java b/src/org/eclipse/jdt/internal/compiler/env/IGenericType.java
index cca5c60..414d190 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/IGenericType.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/IGenericType.java
@@ -11,15 +11,24 @@
package org.eclipse.jdt.internal.compiler.env;
public interface IGenericType extends IDependent {
+
+ // Type decl kinds
+ int CLASS_DECL = 1;
+ int INTERFACE_DECL = 2;
+ int ENUM_DECL = 3;
+ int ANNOTATION_TYPE_DECL = 4;
+
+/**
+ * Returns the kind of this type CLASS, INTERFACE, ENUM, ANNOTATION_TYPE
+ */
+int getKind();
+
/**
* Answer an int whose bits are set according the access constants
* defined by the VM spec.
+ * NOTE 1: We have added AccDeprecated & AccSynthetic.
+ * NOTE 2: If the receiver represents a member type, the modifiers are extracted from its inner class attributes.
*/
-
-// We have added AccDeprecated & AccSynthetic.
-
-// NOTE: If the receiver represents a member type, the modifiers are extracted from its inner class attributes.
-
int getModifiers();
/**
* Answer whether the receiver contains the resolved binary form
@@ -27,6 +36,4 @@ int getModifiers();
*/
boolean isBinaryType();
-boolean isClass();
-boolean isInterface();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java b/src/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
index fc08366..8eba3ab 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
@@ -59,4 +59,14 @@ int getNameSourceStart();
*/
char[] getReturnTypeName();
+/**
+ * Answer the names of the receiver's type parameters
+ * or null if the array is empty.
+ */
+char[][] getTypeParameterNames();
+/**
+ * Answer the array of bound names of the receiver's type parameters
+ * or null if the array is empty.
+ */
+char[][][] getTypeParameterBounds();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/src/org/eclipse/jdt/internal/compiler/env/ISourceType.java
index 594d718..3464fe8 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/ISourceType.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/ISourceType.java
@@ -29,14 +29,14 @@ int getDeclarationSourceStart();
ISourceType getEnclosingType();
/**
- * Answer the receiver's fields or null if the array is empty.
+ * Answer the receiver's fields.
*
* NOTE: Multiple fields with the same name can exist in the result.
*/
ISourceField[] getFields();
/**
- * Answer the receiver's imports or null if the array is empty.
+ * Answer the receiver's imports.
*
* An import is a qualified, dot separated name.
* For example, java.util.Hashtable or java.lang.*.
@@ -55,13 +55,12 @@ ISourceImport[] getImports();
char[][] getInterfaceNames();
/**
- * Answer the receiver's member types
- * or null if the array is empty.
+ * Answer the receiver's member types.
*/
ISourceType[] getMemberTypes();
/**
- * Answer the receiver's methods or null if the array is empty.
+ * Answer the receiver's methods.
*
* NOTE: Multiple methods with the same name & parameter types can exist in the result.
*/
@@ -98,4 +97,12 @@ char[] getPackageName();
* For example, Hashtable or java.util.Hashtable.
*/
char[] getSuperclassName();
+/**
+ * Answer the array of bound names of the receiver's type parameters.
+ */
+char[][][] getTypeParameterBounds();
+/**
+ * Answer the names of the receiver's type parameters.
+ */
+char[][] getTypeParameterNames();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/src/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index b7ab4e6..1f015d5 100644
--- a/src/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/src/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -16,19 +16,28 @@ public class NameEnvironmentAnswer {
IBinaryType binaryType;
ICompilationUnit compilationUnit;
ISourceType[] sourceTypes;
+ AccessRestriction accessRestriction;
- public NameEnvironmentAnswer(IBinaryType binaryType) {
+ public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
this.binaryType = binaryType;
+ this.accessRestriction = accessRestriction;
}
- public NameEnvironmentAnswer(ICompilationUnit compilationUnit) {
+ public NameEnvironmentAnswer(ICompilationUnit compilationUnit, AccessRestriction accessRestriction) {
this.compilationUnit = compilationUnit;
+ this.accessRestriction = accessRestriction;
}
- public NameEnvironmentAnswer(ISourceType[] sourceTypes) {
+ public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction) {
this.sourceTypes = sourceTypes;
+ this.accessRestriction = accessRestriction;
+ }
+ /**
+ * Returns the associated access restriction, or null if none.
+ */
+ public AccessRestriction getAccessRestriction() {
+ return this.accessRestriction;
}
-
/**
* Answer the resolved binary form for the type or null if the
* receiver represents a compilation unit or source type.
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java b/src/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
index 115979e..d7dc642 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
@@ -83,6 +83,42 @@ public class ConditionalFlowInfo extends FlowInfo {
&& initsWhenFalse.isDefinitelyAssigned(local);
}
+ /**
+ * Check status of definite non-null assignment for a field.
+ */
+ public boolean isDefinitelyNonNull(FieldBinding field) {
+
+ return initsWhenTrue.isDefinitelyNonNull(field)
+ && initsWhenFalse.isDefinitelyNonNull(field);
+ }
+
+ /**
+ * Check status of definite non-null assignment for a local variable.
+ */
+ public boolean isDefinitelyNonNull(LocalVariableBinding local) {
+
+ return initsWhenTrue.isDefinitelyNonNull(local)
+ && initsWhenFalse.isDefinitelyNonNull(local);
+ }
+
+ /**
+ * Check status of definite null assignment for a field.
+ */
+ public boolean isDefinitelyNull(FieldBinding field) {
+
+ return initsWhenTrue.isDefinitelyNull(field)
+ && initsWhenFalse.isDefinitelyNull(field);
+ }
+
+ /**
+ * Check status of definite null assignment for a local variable.
+ */
+ public boolean isDefinitelyNull(LocalVariableBinding local) {
+
+ return initsWhenTrue.isDefinitelyNull(local)
+ && initsWhenFalse.isDefinitelyNull(local);
+ }
+
public int reachMode(){
return unconditionalInits().reachMode();
}
@@ -130,6 +166,42 @@ public class ConditionalFlowInfo extends FlowInfo {
}
/**
+ * Record a field got definitely assigned to non-null value.
+ */
+ public void markAsDefinitelyNonNull(FieldBinding field) {
+
+ initsWhenTrue.markAsDefinitelyNonNull(field);
+ initsWhenFalse.markAsDefinitelyNonNull(field);
+ }
+
+ /**
+ * Record a field got definitely assigned to non-null value
+ */
+ public void markAsDefinitelyNonNull(LocalVariableBinding local) {
+
+ initsWhenTrue.markAsDefinitelyNonNull(local);
+ initsWhenFalse.markAsDefinitelyNonNull(local);
+ }
+
+ /**
+ * Record a field got definitely assigned to null.
+ */
+ public void markAsDefinitelyNull(FieldBinding field) {
+
+ initsWhenTrue.markAsDefinitelyNull(field);
+ initsWhenFalse.markAsDefinitelyNull(field);
+ }
+
+ /**
+ * Record a field got definitely assigned to null.
+ */
+ public void markAsDefinitelyNull(LocalVariableBinding local) {
+
+ initsWhenTrue.markAsDefinitelyNull(local);
+ initsWhenFalse.markAsDefinitelyNull(local);
+ }
+
+ /**
* Clear the initialization info for a field
*/
public void markAsDefinitelyNotAssigned(FieldBinding field) {
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/src/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
index d17ab89..0069d50 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.compiler.flow;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -23,9 +24,13 @@ import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
*/
public class FinallyFlowContext extends FlowContext {
- Reference finalAssignments[];
- VariableBinding finalVariables[];
+ Reference[] finalAssignments;
+ VariableBinding[] finalVariables;
int assignCount;
+
+ Expression[] nullReferences;
+ int[] nullStatus;
+ int nullCount;
public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
super(parent, associatedNode);
@@ -36,9 +41,9 @@ public class FinallyFlowContext extends FlowContext {
* code will check that the subroutine context does not also initialize a final variable potentially set
* redundantly.
*/
- public void complainOnRedundantFinalAssignments(
- FlowInfo flowInfo,
- BlockScope scope) {
+ public void complainOnDeferredChecks(FlowInfo flowInfo, BlockScope scope) {
+
+ // check redundant final assignments
for (int i = 0; i < assignCount; i++) {
VariableBinding variable = finalVariables[i];
if (variable == null) continue;
@@ -71,20 +76,43 @@ public class FinallyFlowContext extends FlowContext {
}
}
}
+
+ // check inconsistent null checks
+ for (int i = 0; i < nullCount; i++) {
+ Expression expression = nullReferences[i];
+ if (expression == null) continue;
+ // final local variable
+ LocalVariableBinding local = expression.localVariableBinding();
+ switch (nullStatus[i]) {
+ case FlowInfo.NULL :
+ if (flowInfo.isDefinitelyNull(local)) {
+ nullReferences[i] = null;
+ this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+ }
+ break;
+ case FlowInfo.NON_NULL :
+ if (flowInfo.isDefinitelyNonNull(local)) {
+ nullReferences[i] = null;
+ this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+ }
+ break;
+ }
+ }
}
-
+
public String individualToString() {
StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
- buffer.append("[finalAssignments count -").append(assignCount).append(']'); //$NON-NLS-1$
+ buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
+ buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
return buffer.toString();
}
public boolean isSubRoutine() {
return true;
}
-
- boolean recordFinalAssignment(
+
+ protected boolean recordFinalAssignment(
VariableBinding binding,
Reference finalAssignment) {
if (assignCount == 0) {
@@ -119,4 +147,19 @@ public class FinallyFlowContext extends FlowContext {
}
}
}
+
+ protected boolean recordNullReference(Expression expression, int status) {
+ if (nullCount == 0) {
+ nullReferences = new Expression[5];
+ nullStatus = new int[5];
+ } else {
+ if (nullCount == nullReferences.length) {
+ System.arraycopy(nullReferences, 0, nullReferences = new Expression[nullCount * 2], 0, nullCount);
+ System.arraycopy(nullStatus, 0, nullStatus = new int[nullCount * 2], 0, nullCount);
+ }
+ }
+ nullReferences[nullCount] = expression;
+ nullStatus[nullCount++] = status;
+ return true;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/src/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index 340781f..46b46a5 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -13,11 +13,13 @@ package org.eclipse.jdt.internal.compiler.flow;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.codegen.Label;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -167,7 +169,8 @@ public class FlowContext implements TypeConstants {
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
if (traversedContext.associatedNode instanceof TryStatement){
- flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+ TryStatement tryStatement = (TryStatement) traversedContext.associatedNode;
+ flowInfo = flowInfo.copy().addInitializationsFrom(tryStatement.subRoutineInits);
}
traversedContext = traversedContext.parent;
}
@@ -265,7 +268,8 @@ public class FlowContext implements TypeConstants {
traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
if (traversedContext.associatedNode instanceof TryStatement){
- flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+ TryStatement tryStatement = (TryStatement) traversedContext.associatedNode;
+ flowInfo = flowInfo.copy().addInitializationsFrom(tryStatement.subRoutineInits);
}
traversedContext = traversedContext.parent;
}
@@ -427,13 +431,18 @@ public class FlowContext implements TypeConstants {
// default implementation: do nothing
}
- boolean recordFinalAssignment(
+ protected boolean recordFinalAssignment(
VariableBinding variable,
Reference finalReference) {
return true; // keep going
}
+ protected boolean recordNullReference(Expression expression, int status) {
+
+ return false; // keep going
+ }
+
public void recordReturnFrom(FlowInfo flowInfo) {
// default implementation: do nothing
}
@@ -455,6 +464,38 @@ public class FlowContext implements TypeConstants {
}
}
+ public void recordUsingNullReference(Scope scope, LocalVariableBinding local, Expression reference, int status, FlowInfo flowInfo) {
+
+ if (!flowInfo.isReachable()) return;
+
+ switch (status) {
+ case FlowInfo.NULL :
+ if (flowInfo.isDefinitelyNull(local)) {
+ scope.problemReporter().localVariableCanOnlyBeNull(local, reference);
+ return;
+ } else if (flowInfo.isDefinitelyNonNull(local)) {
+ scope.problemReporter().localVariableCannotBeNull(local, reference);
+ return;
+ }
+ break;
+ case FlowInfo.NON_NULL :
+ if (flowInfo.isDefinitelyNull(local)) {
+ scope.problemReporter().localVariableCanOnlyBeNull(local, reference);
+ return;
+ }
+ break;
+ }
+
+ // for initialization inside looping statement that effectively loops
+ FlowContext context = this;
+ while (context != null) {
+ if (context.recordNullReference(reference, status)) {
+ return; // no need to keep going
+ }
+ context = context.parent;
+ }
+ }
+
void removeFinalAssignmentIfAny(Reference reference) {
// default implementation: do nothing
}
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/src/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 1736a5c..3219a62 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -16,7 +16,11 @@ import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
public abstract class FlowInfo {
public final static int REACHABLE = 0;
- public final static int UNREACHABLE = 1;
+ public final static int UNREACHABLE = 1;
+
+ public final static int UNKNOWN = 0;
+ public final static int NULL = 1;
+ public final static int NON_NULL = -1;
public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
static {
@@ -60,7 +64,25 @@ public abstract class FlowInfo {
*/
public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
- //abstract public int reachMode();
+ /**
+ * Check status of definite null assignment for a field.
+ */
+ abstract public boolean isDefinitelyNonNull(FieldBinding field);
+
+ /**
+ * Check status of definite null assignment for a local.
+ */
+ public abstract boolean isDefinitelyNonNull(LocalVariableBinding local);
+
+ /**
+ * Check status of definite null assignment for a field.
+ */
+ abstract public boolean isDefinitelyNull(FieldBinding field);
+
+ /**
+ * Check status of definite null assignment for a local.
+ */
+ public abstract boolean isDefinitelyNull(LocalVariableBinding local);
/**
* Check status of potential assignment for a field.
@@ -81,6 +103,26 @@ public abstract class FlowInfo {
abstract public void markAsDefinitelyAssigned(FieldBinding field);
/**
+ * Record a local got definitely assigned to a non-null value.
+ */
+ abstract public void markAsDefinitelyNonNull(LocalVariableBinding local);
+
+ /**
+ * Record a field got definitely assigned to a non-null value.
+ */
+ abstract public void markAsDefinitelyNonNull(FieldBinding field);
+
+ /**
+ * Record a local got definitely assigned to null.
+ */
+ abstract public void markAsDefinitelyNull(LocalVariableBinding local);
+
+ /**
+ * Record a field got definitely assigned.
+ */
+ abstract public void markAsDefinitelyNull(FieldBinding field);
+
+ /**
* Record a local got definitely assigned.
*/
abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/src/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 450bdff..9f1ed05 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.compiler.flow;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.codegen.Label;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -30,6 +31,11 @@ public class LoopingFlowContext extends SwitchFlowContext {
Reference finalAssignments[];
VariableBinding finalVariables[];
int assignCount = 0;
+
+ Expression[] nullReferences;
+ int[] nullStatus;
+ int nullCount;
+
Scope associatedScope;
public LoopingFlowContext(
@@ -43,9 +49,9 @@ public class LoopingFlowContext extends SwitchFlowContext {
this.associatedScope = associatedScope;
}
- public void complainOnFinalAssignmentsInLoop(
- BlockScope scope,
- FlowInfo flowInfo) {
+ public void complainOnDeferredChecks(BlockScope scope, FlowInfo flowInfo) {
+
+ // complain on final assignments in loops
for (int i = 0; i < assignCount; i++) {
VariableBinding variable = finalVariables[i];
if (variable == null) continue;
@@ -75,6 +81,27 @@ public class LoopingFlowContext extends SwitchFlowContext {
}
}
}
+ // check inconsistent null checks
+ for (int i = 0; i < nullCount; i++) {
+ Expression expression = nullReferences[i];
+ if (expression == null) continue;
+ // final local variable
+ LocalVariableBinding local = expression.localVariableBinding();
+ switch (nullStatus[i]) {
+ case FlowInfo.NULL :
+ if (flowInfo.isDefinitelyNull(local)) {
+ nullReferences[i] = null;
+ this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+ }
+ break;
+ case FlowInfo.NON_NULL :
+ if (flowInfo.isDefinitelyNonNull(local)) {
+ nullReferences[i] = null;
+ this.parent.recordUsingNullReference(scope, local, expression, nullStatus[i], flowInfo);
+ }
+ break;
+ }
+ }
}
public Label continueLabel() {
@@ -83,8 +110,10 @@ public class LoopingFlowContext extends SwitchFlowContext {
public String individualToString() {
StringBuffer buffer = new StringBuffer("Looping flow context"); //$NON-NLS-1$
- buffer.append("[initsOnBreak -").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
- buffer.append("[initsOnContinue -").append(initsOnContinue.toString()).append(']'); //$NON-NLS-1$
+ buffer.append("[initsOnBreak - ").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
+ buffer.append("[initsOnContinue - ").append(initsOnContinue.toString()).append(']'); //$NON-NLS-1$
+ buffer.append("[finalAssignments count - ").append(assignCount).append(']'); //$NON-NLS-1$
+ buffer.append("[nullReferences count - ").append(nullCount).append(']'); //$NON-NLS-1$
return buffer.toString();
}
@@ -106,7 +135,7 @@ public class LoopingFlowContext extends SwitchFlowContext {
}
}
- boolean recordFinalAssignment(
+ protected boolean recordFinalAssignment(
VariableBinding binding,
Reference finalAssignment) {
@@ -141,6 +170,21 @@ public class LoopingFlowContext extends SwitchFlowContext {
return true;
}
+ protected boolean recordNullReference(Expression expression, int status) {
+ if (nullCount == 0) {
+ nullReferences = new Expression[5];
+ nullStatus = new int[5];
+ } else {
+ if (nullCount == nullReferences.length) {
+ System.arraycopy(nullReferences, 0, nullReferences = new Expression[nullCount * 2], 0, nullCount);
+ System.arraycopy(nullStatus, 0, nullStatus = new int[nullCount * 2], 0, nullCount);
+ }
+ }
+ nullReferences[nullCount] = expression;
+ nullStatus[nullCount++] = status;
+ return true;
+ }
+
void removeFinalAssignmentIfAny(Reference reference) {
for (int i = 0; i < assignCount; i++) {
if (finalAssignments[i] == reference) {
diff --git a/src/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/src/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 4ae4c52..88cd296 100644
--- a/src/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/src/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -28,6 +27,11 @@ public class UnconditionalFlowInfo extends FlowInfo {
public long extraDefiniteInits[];
public long extraPotentialInits[];
+ public long definiteNulls;
+ public long definiteNonNulls;
+ public long extraDefiniteNulls[];
+ public long extraDefiniteNonNulls[];
+
public int reachMode; // by default
public int maxFieldCount;
@@ -54,6 +58,12 @@ public class UnconditionalFlowInfo extends FlowInfo {
// union of potentially set ones
potentialInits |= otherInits.potentialInits;
+ // union of definitely null variables,
+ definiteNulls = (definiteNulls | otherInits.definiteNulls) & ~otherInits.definiteNonNulls;
+ // union of definitely non null variables,
+ definiteNonNulls = (definiteNonNulls | otherInits.definiteNonNulls) & ~otherInits.definiteNulls;
+ // fix-up null/non-null infos since cannot overlap: + -->
+
// treating extra storage
if (extraDefiniteInits != null) {
if (otherInits.extraDefiniteInits != null) {
@@ -63,21 +73,28 @@ public class UnconditionalFlowInfo extends FlowInfo {
// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength]), 0, length);
System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, length);
- while (i < length) {
+ for (; i < length; i++) {
extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
- extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ extraDefiniteNulls[i] = (extraDefiniteNulls[i] | otherInits.extraDefiniteNulls[i]) & ~otherInits.extraDefiniteNonNulls[i];
+ extraDefiniteNonNulls[i] = (extraDefiniteNonNulls[i] | otherInits.extraDefiniteNonNulls[i]) & ~otherInits.extraDefiniteNulls[i];
}
- while (i < otherLength) {
- extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+ for (; i < otherLength; i++) {
+ extraPotentialInits[i] = otherInits.extraPotentialInits[i];
}
} else {
// current storage is longer
- while (i < otherLength) {
+ for (; i < otherLength; i++) {
extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
- extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ extraDefiniteNulls[i] = (extraDefiniteNulls[i] | otherInits.extraDefiniteNulls[i]) & ~otherInits.extraDefiniteNonNulls[i];
+ extraDefiniteNonNulls[i] = (extraDefiniteNonNulls[i] | otherInits.extraDefiniteNonNulls[i]) & ~otherInits.extraDefiniteNulls[i];
+ }
+ for (; i < length; i++) {
+ extraDefiniteInits[i] = 0;
+ extraDefiniteNulls[i] = 0;
+ extraDefiniteNonNulls[i] = 0;
}
- while (i < length)
- extraDefiniteInits[i++] = 0;
}
} else {
// no extra storage on otherInits
@@ -88,6 +105,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
int otherLength;
System.arraycopy(otherInits.extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length]), 0, otherLength);
System.arraycopy(otherInits.extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, otherLength);
+ System.arraycopy(otherInits.extraDefiniteNulls, 0, (extraDefiniteNulls = new long[otherLength]), 0, otherLength);
+ System.arraycopy(otherInits.extraDefiniteNonNulls, 0, (extraDefiniteNonNulls = new long[otherLength]), 0, otherLength);
}
return this;
}
@@ -104,27 +123,38 @@ public class UnconditionalFlowInfo extends FlowInfo {
return this;
}
// union of potentially set ones
- potentialInits |= otherInits.potentialInits;
+ this.potentialInits |= otherInits.potentialInits;
+ // also merge null check information (affected by potential inits)
+ this.definiteNulls &= otherInits.definiteNulls;
+ this.definiteNonNulls &= otherInits.definiteNonNulls;
// treating extra storage
- if (extraDefiniteInits != null) {
+ if (this.extraDefiniteInits != null) {
if (otherInits.extraDefiniteInits != null) {
// both sides have extra storage
int i = 0, length, otherLength;
- if ((length = extraDefiniteInits.length) < (otherLength = otherInits.extraDefiniteInits.length)) {
+ if ((length = this.extraDefiniteInits.length) < (otherLength = otherInits.extraDefiniteInits.length)) {
// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
- System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[otherLength]), 0, length);
- System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraDefiniteInits, 0, (this.extraDefiniteInits = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraDefiniteNulls, 0, (this.extraDefiniteNulls = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraDefiniteNonNulls, 0, (this.extraDefiniteNonNulls = new long[otherLength]), 0, length);
while (i < length) {
- extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+ this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
}
while (i < otherLength) {
- extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+ this.extraPotentialInits[i] = otherInits.extraPotentialInits[i];
+ this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+ this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
}
} else {
// current storage is longer
while (i < otherLength) {
- extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+ this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
}
}
}
@@ -132,8 +162,10 @@ public class UnconditionalFlowInfo extends FlowInfo {
if (otherInits.extraDefiniteInits != null) {
// no storage here, but other has extra storage.
int otherLength;
- extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];
- System.arraycopy(otherInits.extraPotentialInits, 0, (extraPotentialInits = new long[otherLength]), 0, otherLength);
+ this.extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];
+ System.arraycopy(otherInits.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, otherLength);
+ this.extraDefiniteNulls = new long[otherLength];
+ this.extraDefiniteNonNulls = new long[otherLength];
}
return this;
}
@@ -153,13 +185,17 @@ public class UnconditionalFlowInfo extends FlowInfo {
// copy slots
copy.definiteInits = this.definiteInits;
copy.potentialInits = this.potentialInits;
+ copy.definiteNulls = this.definiteNulls;
+ copy.definiteNonNulls = this.definiteNonNulls;
copy.reachMode = this.reachMode;
copy.maxFieldCount = this.maxFieldCount;
if (this.extraDefiniteInits != null) {
int length;
- System.arraycopy(this.extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[ (length = extraDefiniteInits.length)]), 0, length);
+ System.arraycopy(this.extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[length = extraDefiniteInits.length]), 0, length);
System.arraycopy(this.extraPotentialInits, 0, (copy.extraPotentialInits = new long[length]), 0, length);
+ System.arraycopy(this.extraDefiniteNulls, 0, (copy.extraDefiniteNulls = new long[length]), 0, length);
+ System.arraycopy(this.extraDefiniteNonNulls, 0, (copy.extraDefiniteNonNulls = new long[length]), 0, length);
}
return copy;
}
@@ -172,12 +208,16 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask = (1L << limit)-1;
this.definiteInits &= ~mask;
this.potentialInits &= ~mask;
+ this.definiteNulls &= ~mask;
+ this.definiteNonNulls &= ~mask;
return this;
}
this.definiteInits = 0;
this.potentialInits = 0;
-
+ this.definiteNulls = 0;
+ this.definiteNonNulls = 0;
+
// use extra vector
if (extraDefiniteInits == null) {
return this; // if vector not yet allocated, then not initialized
@@ -189,10 +229,14 @@ public class UnconditionalFlowInfo extends FlowInfo {
for (int i = 0; i < vectorIndex; i++) {
this.extraDefiniteInits[i] = 0L;
this.extraPotentialInits[i] = 0L;
+ this.extraDefiniteNulls[i] = 0L;
+ this.extraDefiniteNonNulls[i] = 0L;
}
long mask = (1L << (limit % BitCacheSize))-1;
this.extraDefiniteInits[vectorIndex] &= ~mask;
this.extraPotentialInits[vectorIndex] &= ~mask;
+ this.extraDefiniteNulls[vectorIndex] &= ~mask;
+ this.extraDefiniteNonNulls[vectorIndex] &= ~mask;
return this;
}
@@ -204,6 +248,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask = (1L << limit)-1;
this.definiteInits &= mask;
this.potentialInits &= mask;
+ this.definiteNulls &= mask;
+ this.definiteNonNulls &= mask;
return this;
}
// use extra vector
@@ -217,13 +263,30 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask = (1L << (limit % BitCacheSize))-1;
this.extraDefiniteInits[vectorIndex] &= mask;
this.extraPotentialInits[vectorIndex] &= mask;
+ this.extraDefiniteNulls[vectorIndex] &= mask;
+ this.extraDefiniteNonNulls[vectorIndex] &= mask;
for (int i = vectorIndex+1; i < length; i++) {
this.extraDefiniteInits[i] = 0L;
this.extraPotentialInits[i] = 0L;
+ this.extraDefiniteNulls[i] = 0L;
+ this.extraDefiniteNonNulls[i] = 0L;
}
return this;
}
+ public UnconditionalFlowInfo discardNullRelatedInitializations(){
+
+ this.definiteNulls = 0;
+ this.definiteNonNulls = 0;
+
+ int length = this.extraDefiniteInits == null ? 0 : this.extraDefiniteInits.length;
+ for (int i = 0; i < length; i++) {
+ this.extraDefiniteNulls[i] = 0L;
+ this.extraDefiniteNonNulls[i] = 0L;
+ }
+ return this;
+ }
+
public FlowInfo initsWhenFalse() {
return this;
@@ -256,6 +319,48 @@ public class UnconditionalFlowInfo extends FlowInfo {
}
/**
+ * Check status of definite non-null assignment at a given position.
+ * It deals with the dual representation of the InitializationInfo2:
+ * bits for the first 64 entries, then an array of booleans.
+ */
+ final private boolean isDefinitelyNonNull(int position) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // id is zero-based
+ if (position < BitCacheSize) {
+ return (definiteNonNulls & (1L << position)) != 0; // use bits
+ }
+ // use extra vector
+ if (extraDefiniteNonNulls == null)
+ return false; // if vector not yet allocated, then not initialized
+ int vectorIndex;
+ if ((vectorIndex = (position / BitCacheSize) - 1) >= extraDefiniteNonNulls.length)
+ return false; // if not enough room in vector, then not initialized
+ return ((extraDefiniteNonNulls[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+ }
+
+ /**
+ * Check status of definite null assignment at a given position.
+ * It deals with the dual representation of the InitializationInfo2:
+ * bits for the first 64 entries, then an array of booleans.
+ */
+ final private boolean isDefinitelyNull(int position) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // id is zero-based
+ if (position < BitCacheSize) {
+ return (definiteNulls & (1L << position)) != 0; // use bits
+ }
+ // use extra vector
+ if (extraDefiniteNulls == null)
+ return false; // if vector not yet allocated, then not initialized
+ int vectorIndex;
+ if ((vectorIndex = (position / BitCacheSize) - 1) >= extraDefiniteNulls.length)
+ return false; // if not enough room in vector, then not initialized
+ return ((extraDefiniteNulls[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+ }
+
+ /**
* Check status of definite assignment for a field.
*/
final public boolean isDefinitelyAssigned(FieldBinding field) {
@@ -276,16 +381,66 @@ public class UnconditionalFlowInfo extends FlowInfo {
// We do not want to complain in unreachable code
if ((this.reachMode & UNREACHABLE) != 0)
return true;
- if (local.isArgument) {
+
+ // final constants are inlined, and thus considered as always initialized
+ if (local.isConstantValue()) {
return true;
}
+ return isDefinitelyAssigned(local.id + maxFieldCount);
+ }
+
+ /**
+ * Check status of definite non-null assignment for a field.
+ */
+ final public boolean isDefinitelyNonNull(FieldBinding field) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // We do not want to complain in unreachable code
+ if ((this.reachMode & UNREACHABLE) != 0)
+ return false;
+ return isDefinitelyNonNull(field.id);
+ }
+
+ /**
+ * Check status of definite non-null assignment for a local.
+ */
+ final public boolean isDefinitelyNonNull(LocalVariableBinding local) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // We do not want to complain in unreachable code
+ if ((this.reachMode & UNREACHABLE) != 0)
+ return false;
// final constants are inlined, and thus considered as always initialized
- if (local.constant != Constant.NotAConstant) {
+ if (local.isConstantValue()) {
return true;
}
- return isDefinitelyAssigned(local.id + maxFieldCount);
+ return isDefinitelyNonNull(local.id + maxFieldCount);
+ }
+
+ /**
+ * Check status of definite null assignment for a field.
+ */
+ final public boolean isDefinitelyNull(FieldBinding field) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // We do not want to complain in unreachable code
+ if ((this.reachMode & UNREACHABLE) != 0)
+ return false;
+ return isDefinitelyNull(field.id);
}
+ /**
+ * Check status of definite null assignment for a local.
+ */
+ final public boolean isDefinitelyNull(LocalVariableBinding local) {
+
+ // Dependant of CodeStream.isDefinitelyAssigned(..)
+ // We do not want to complain in unreachable code
+ if ((this.reachMode & UNREACHABLE) != 0)
+ return false;
+ return isDefinitelyNull(local.id + maxFieldCount);
+ }
+
public boolean isReachable() {
return this.reachMode == REACHABLE;
@@ -325,11 +480,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
*/
final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
- if (local.isArgument) {
- return true;
- }
// final constants are inlined, and thus considered as always initialized
- if (local.constant != Constant.NotAConstant) {
+ if (local.isConstantValue()) {
return true;
}
return isPotentiallyAssigned(local.id + maxFieldCount);
@@ -350,6 +502,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask;
definiteInits |= (mask = 1L << position);
potentialInits |= mask;
+ definiteNulls &= ~mask;
+ definiteNonNulls &= ~mask;
} else {
// use extra vector
int vectorIndex = (position / BitCacheSize) - 1;
@@ -357,16 +511,22 @@ public class UnconditionalFlowInfo extends FlowInfo {
int length;
extraDefiniteInits = new long[length = vectorIndex + 1];
extraPotentialInits = new long[length];
+ extraDefiniteNulls = new long[length];
+ extraDefiniteNonNulls = new long[length];
} else {
int oldLength; // might need to grow the arrays
if (vectorIndex >= (oldLength = extraDefiniteInits.length)) {
System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[vectorIndex + 1]), 0, oldLength);
System.arraycopy(extraPotentialInits, 0, (extraPotentialInits = new long[vectorIndex + 1]), 0, oldLength);
+ System.arraycopy(extraDefiniteNulls, 0, (extraDefiniteNulls = new long[vectorIndex + 1]), 0, oldLength);
+ System.arraycopy(extraDefiniteNonNulls, 0, (extraDefiniteNonNulls = new long[vectorIndex + 1]), 0, oldLength);
}
}
long mask;
extraDefiniteInits[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
extraPotentialInits[vectorIndex] |= mask;
+ extraDefiniteNulls[vectorIndex] &= ~mask;
+ extraDefiniteNonNulls[vectorIndex] &= ~mask;
}
}
}
@@ -386,6 +546,88 @@ public class UnconditionalFlowInfo extends FlowInfo {
if (this != DEAD_END)
markAsDefinitelyAssigned(local.id + maxFieldCount);
}
+
+ /**
+ * Record a definite non-null assignment at a given position.
+ * It deals with the dual representation of the InitializationInfo2:
+ * bits for the first 64 entries, then an array of booleans.
+ */
+ final private void markAsDefinitelyNonNull(int position) {
+
+ if (this != DEAD_END) {
+
+ // position is zero-based
+ if (position < BitCacheSize) {
+ // use bits
+ long mask;
+ definiteNonNulls |= (mask = 1L << position);
+ definiteNulls &= ~mask;
+ } else {
+ // use extra vector
+ int vectorIndex = (position / BitCacheSize) - 1;
+ long mask;
+ extraDefiniteNonNulls[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
+ extraDefiniteNulls[vectorIndex] &= ~mask;
+ }
+ }
+ }
+
+ /**
+ * Record a field got definitely assigned to non-null value.
+ */
+ public void markAsDefinitelyNonNull(FieldBinding field) {
+ if (this != DEAD_END)
+ markAsDefinitelyNonNull(field.id);
+ }
+
+ /**
+ * Record a local got definitely assigned to non-null value.
+ */
+ public void markAsDefinitelyNonNull(LocalVariableBinding local) {
+ if (this != DEAD_END)
+ markAsDefinitelyNonNull(local.id + maxFieldCount);
+ }
+
+ /**
+ * Record a definite null assignment at a given position.
+ * It deals with the dual representation of the InitializationInfo2:
+ * bits for the first 64 entries, then an array of booleans.
+ */
+ final private void markAsDefinitelyNull(int position) {
+
+ if (this != DEAD_END) {
+
+ // position is zero-based
+ if (position < BitCacheSize) {
+ // use bits
+ long mask;
+ definiteNulls |= (mask = 1L << position);
+ definiteNonNulls &= ~mask;
+ } else {
+ // use extra vector
+ int vectorIndex = (position / BitCacheSize) - 1;
+ long mask;
+ extraDefiniteNulls[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
+ extraDefiniteNonNulls[vectorIndex] &= ~mask;
+ }
+ }
+ }
+
+ /**
+ * Record a field got definitely assigned to null.
+ */
+ public void markAsDefinitelyNull(FieldBinding field) {
+ if (this != DEAD_END)
+ markAsDefinitelyAssigned(field.id);
+ }
+
+ /**
+ * Record a local got definitely assigned to null.
+ */
+ public void markAsDefinitelyNull(LocalVariableBinding local) {
+ if (this != DEAD_END)
+ markAsDefinitelyNull(local.id + maxFieldCount);
+ }
/**
* Clear initialization information at a given position.
@@ -401,6 +643,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask;
definiteInits &= ~(mask = 1L << position);
potentialInits &= ~mask;
+ definiteNulls &= ~mask;
+ definiteNonNulls &= ~mask;
} else {
// use extra vector
int vectorIndex = (position / BitCacheSize) - 1;
@@ -414,6 +658,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
long mask;
extraDefiniteInits[vectorIndex] &= ~(mask = 1L << (position % BitCacheSize));
extraPotentialInits[vectorIndex] &= ~mask;
+ extraDefiniteNulls[vectorIndex] &= ~mask;
+ extraDefiniteNonNulls[vectorIndex] &= ~mask;
}
}
}
@@ -462,6 +708,10 @@ public class UnconditionalFlowInfo extends FlowInfo {
this.definiteInits &= otherInits.definiteInits;
// union of potentially set ones
this.potentialInits |= otherInits.potentialInits;
+ // intersection of definitely null variables,
+ this.definiteNulls &= otherInits.definiteNulls;
+ // intersection of definitely non-null variables,
+ this.definiteNonNulls &= otherInits.definiteNonNulls;
// treating extra storage
if (this.extraDefiniteInits != null) {
@@ -472,9 +722,13 @@ public class UnconditionalFlowInfo extends FlowInfo {
// current storage is shorter -> grow current (could maybe reuse otherInits extra storage?)
System.arraycopy(this.extraDefiniteInits, 0, (this.extraDefiniteInits = new long[otherLength]), 0, length);
System.arraycopy(this.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraDefiniteNulls, 0, (this.extraDefiniteNulls = new long[otherLength]), 0, length);
+ System.arraycopy(this.extraDefiniteNonNulls, 0, (this.extraDefiniteNonNulls = new long[otherLength]), 0, length);
while (i < length) {
this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
- this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+ this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
}
while (i < otherLength) {
this.extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
@@ -483,16 +737,24 @@ public class UnconditionalFlowInfo extends FlowInfo {
// current storage is longer
while (i < otherLength) {
this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
- this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+ this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i];
+ this.extraDefiniteNulls[i] &= otherInits.extraDefiniteNulls[i];
+ this.extraDefiniteNonNulls[i] &= otherInits.extraDefiniteNonNulls[i++];
+ }
+ while (i < length) {
+ this.extraDefiniteInits[i] = 0;
+ this.extraDefiniteNulls[i] = 0;
+ this.extraDefiniteNonNulls[i++] = 0;
}
- while (i < length)
- this.extraDefiniteInits[i++] = 0;
}
} else {
// no extra storage on otherInits
int i = 0, length = this.extraDefiniteInits.length;
- while (i < length)
- this.extraDefiniteInits[i++] = 0;
+ while (i < length) {
+ this.extraDefiniteInits[i] = 0;
+ this.extraDefiniteNulls[i] = 0;
+ this.extraDefiniteNonNulls[i++] = 0;
+ }
}
} else
if (otherInits.extraDefiniteInits != null) {
@@ -500,6 +762,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
int otherLength;
this.extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];
System.arraycopy(otherInits.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, otherLength);
+ this.extraDefiniteNulls = new long[otherLength];
+ this.extraDefiniteNonNulls = new long[otherLength];
}
return this;
}
@@ -548,6 +812,8 @@ public class UnconditionalFlowInfo extends FlowInfo {
return "FlowInfo"; //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/src/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 0d729a4..78f82b8 100644
--- a/src/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/src/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -55,6 +55,7 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
public static final String OPTION_ReportUnusedPrivateMember = "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
public static final String OPTION_ReportNoImplicitStringConversion = "org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion"; //$NON-NLS-1$
public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
+ public static final String OPTION_ReportEnumIdentifier = "org.eclipse.jdt.core.compiler.problem.enumIdentifier"; //$NON-NLS-1$
public static final String OPTION_ReportNonStaticAccessToStatic = "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
public static final String OPTION_ReportIndirectStaticAccess = "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
public static final String OPTION_ReportEmptyStatement = "org.eclipse.jdt.core.compiler.problem.emptyStatement"; //$NON-NLS-1$
@@ -63,6 +64,8 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
public static final String OPTION_ReportUndocumentedEmptyBlock = "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
public static final String OPTION_ReportInvalidJavadoc = "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"; //$NON-NLS-1$
public static final String OPTION_ReportInvalidJavadocTags = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+ public static final String OPTION_ReportInvalidJavadocTagsDeprecatedRef = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"; //$NON-NLS-1$
+ public static final String OPTION_ReportInvalidJavadocTagsNotVisibleRef = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"; //$NON-NLS-1$
public static final String OPTION_ReportInvalidJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
public static final String OPTION_ReportMissingJavadocTags = "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"; //$NON-NLS-1$
public static final String OPTION_ReportMissingJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
@@ -74,6 +77,10 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
public static final String OPTION_ReportUnusedDeclaredThrownException = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
public static final String OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"; //$NON-NLS-1$
public static final String OPTION_ReportUnqualifiedFieldAccess = "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$
+ public static final String OPTION_ReportUnsafeTypeOperation = "org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation"; //$NON-NLS-1$
+ public static final String OPTION_ReportFinalParameterBound = "org.eclipse.jdt.core.compiler.problem.finalParameterBound"; //$NON-NLS-1$
+ public static final String OPTION_ReportMissingSerialVersion = "org.eclipse.jdt.core.compiler.problem.missingSerialVersion"; //$NON-NLS-1$
+ public static final String OPTION_ReportVarargsArgumentNeedCast = "org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast"; //$NON-NLS-1$
public static final String OPTION_Source = "org.eclipse.jdt.core.compiler.source"; //$NON-NLS-1$
public static final String OPTION_TargetPlatform = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$
public static final String OPTION_Compliance = "org.eclipse.jdt.core.compiler.compliance"; //$NON-NLS-1$
@@ -83,6 +90,12 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
public static final String OPTION_TaskPriorities = "org.eclipse.jdt.core.compiler.taskPriorities"; //$NON-NLS-1$
public static final String OPTION_TaskCaseSensitive = "org.eclipse.jdt.core.compiler.taskCaseSensitive"; //$NON-NLS-1$
public static final String OPTION_InlineJsr = "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"; //$NON-NLS-1$
+ public static final String OPTION_ReportInconsistentNullCheck = "org.eclipse.jdt.core.compiler.problem.inconsistentNullCheck"; //$NON-NLS-1$
+ public static final String OPTION_ReportForbiddenReference = "org.eclipse.jdt.core.compiler.problem.forbiddenReference"; //$NON-NLS-1$
+ public static final String OPTION_ImportRestrictionInclude = "org.eclipse.jdt.core.compiler.accessRestriction.import.include"; //$NON-NLS-1$
+ public static final String OPTION_ImportRestrictionExclude = "org.eclipse.jdt.core.compiler.accessRestriction.import.exclude"; //$NON-NLS-1$
+ public static final String OPTION_ExportRestrictionInclude = "org.eclipse.jdt.core.compiler.accessRestriction.export.include"; //$NON-NLS-1$
+ public static final String OPTION_ExportRestrictionExclude = "org.eclipse.jdt.core.compiler.accessRestriction.export.exclude"; //$NON-NLS-1$
// Backward compatibility
public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$
@@ -147,6 +160,13 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
public static final long UndocumentedEmptyBlock = ASTNode.Bit28;
public static final long IndirectStaticAccess = ASTNode.Bit29;
public static final long UnnecessaryElse = ASTNode.Bit30;
+ public static final long UnsafeTypeOperation = ASTNode.Bit31;
+ public static final long FinalParameterBound = ASTNode.Bit32L;
+ public static final long MissingSerialVersion = ASTNode.Bit33L;
+ public static final long EnumUsedAsAnIdentifier = ASTNode.Bit34L;
+ public static final long ForbiddenReference = ASTNode.Bit35L;
+ public static final long VarargsArgumentNeedCast = ASTNode.Bit36L;
+ public static final long InconsistentNullCheck = ASTNode.Bit37L;
// Default severity level for handlers
public long errorThreshold = 0;
@@ -162,7 +182,13 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
| IncompatibleNonInheritedInterfaceMethod
| NoImplicitStringConversion
| FinallyBlockNotCompleting
- | AssertUsedAsAnIdentifier;
+ | AssertUsedAsAnIdentifier
+ | EnumUsedAsAnIdentifier
+ | UnsafeTypeOperation
+ | MissingSerialVersion
+ | VarargsArgumentNeedCast
+ | ForbiddenReference
+ /*| InconsistentNullCheck*/;
// Debug attributes
public static final int Source = 1; // SourceFileAttribute
@@ -197,6 +223,12 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
// max problems per compilation unit
public int maxProblemsPerUnit = 100; // no more than 100 problems per default
+ // access restrictions
+ public char[][] importRestrictionInclude;
+ public char[][] importRestrictionExclude;
+ public char[][] exportRestrictionInclude;
+ public char[][] exportRestrictionExclude;
+
// tags used to recognize tasks in comments
public char[][] taskTags = null;
public char[][] taskPriorites = null;
@@ -216,9 +248,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
// constructor/setter parameter hiding
public boolean reportSpecialParameterHidingField = false;
- // check javadoc comments
+ // check javadoc comments tags
public int reportInvalidJavadocTagsVisibility = AccPrivate;
- public boolean reportInvalidJavadocTags = true;
+ public boolean reportInvalidJavadocTags = true;
+ public boolean reportInvalidJavadocTagsDeprecatedRef = true;
+ public boolean reportInvalidJavadocTagsNotVisibleRef = true;
// check missing javadoc tags
public int reportMissingJavadocTagsVisibility = AccPrivate;
@@ -281,12 +315,15 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
optionsMap.put(OPTION_ReportPossibleAccidentalBooleanAssignment, getSeverityString(AccidentalBooleanAssign));
optionsMap.put(OPTION_ReportEmptyStatement, getSeverityString(EmptyStatement));
optionsMap.put(OPTION_ReportAssertIdentifier, getSeverityString(AssertUsedAsAnIdentifier));
+ optionsMap.put(OPTION_ReportEnumIdentifier, getSeverityString(EnumUsedAsAnIdentifier));
optionsMap.put(OPTION_ReportUndocumentedEmptyBlock, getSeverityString(UndocumentedEmptyBlock));
optionsMap.put(OPTION_ReportUnnecessaryTypeCheck, getSeverityString(UnnecessaryTypeCheck));
optionsMap.put(OPTION_ReportUnnecessaryElse, getSeverityString(UnnecessaryElse));
optionsMap.put(OPTION_ReportInvalidJavadoc, getSeverityString(InvalidJavadoc));
optionsMap.put(OPTION_ReportInvalidJavadocTagsVisibility, getVisibilityString(this.reportInvalidJavadocTagsVisibility));
- optionsMap.put(OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags? ENABLED : DISABLED);
+ optionsMap.put(OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_ReportInvalidJavadocTagsDeprecatedRef, this.reportInvalidJavadocTagsDeprecatedRef ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_ReportInvalidJavadocTagsNotVisibleRef, this.reportInvalidJavadocTagsNotVisibleRef ? ENABLED : DISABLED);
optionsMap.put(OPTION_ReportMissingJavadocTags, getSeverityString(MissingJavadocTags));
optionsMap.put(OPTION_ReportMissingJavadocTagsVisibility, getVisibilityString(this.reportMissingJavadocTagsVisibility));
optionsMap.put(OPTION_ReportMissingJavadocTagsOverriding, this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED);
@@ -297,6 +334,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException));
optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED);
optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess));
+ optionsMap.put(OPTION_ReportUnsafeTypeOperation, getSeverityString(UnsafeTypeOperation));
+ optionsMap.put(OPTION_ReportFinalParameterBound, getSeverityString(FinalParameterBound));
+ optionsMap.put(OPTION_ReportMissingSerialVersion, getSeverityString(MissingSerialVersion));
+ optionsMap.put(OPTION_ReportForbiddenReference, getSeverityString(ForbiddenReference));
+ optionsMap.put(OPTION_ReportVarargsArgumentNeedCast, getSeverityString(VarargsArgumentNeedCast));
optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel));
optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel));
optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK));
@@ -311,6 +353,11 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
optionsMap.put(OPTION_ReportSpecialParameterHidingField, this.reportSpecialParameterHidingField ? ENABLED : DISABLED);
optionsMap.put(OPTION_MaxProblemPerUnit, String.valueOf(this.maxProblemsPerUnit));
optionsMap.put(OPTION_InlineJsr, this.inlineJsrBytecode ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_ImportRestrictionInclude, this.importRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionInclude,','))); //$NON-NLS-1$
+ optionsMap.put(OPTION_ImportRestrictionExclude, this.importRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionExclude,','))); //$NON-NLS-1$
+ optionsMap.put(OPTION_ImportRestrictionInclude, this.exportRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionInclude,','))); //$NON-NLS-1$
+ optionsMap.put(OPTION_ExportRestrictionExclude, this.exportRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionExclude,','))); //$NON-NLS-1$
+ optionsMap.put(OPTION_ReportInconsistentNullCheck, getSeverityString(InconsistentNullCheck));
return optionsMap;
}
@@ -406,6 +453,7 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
if ((optionValue = optionsMap.get(OPTION_TargetPlatform)) != null) {
long level = versionToJdkLevel(optionValue);
if (level != 0) this.targetJDK = level;
+ if (this.targetJDK >= JDK1_5) this.inlineJsrBytecode = true; // forced in 1.5 mode
}
if ((optionValue = optionsMap.get(OPTION_Encoding)) != null) {
if (optionValue instanceof String) {
@@ -484,11 +532,53 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
this.isTaskCaseSensitive = false;
}
}
+ if ((optionValue = optionsMap.get(OPTION_ImportRestrictionInclude)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() == 0) {
+ this.importRestrictionInclude = null;
+ } else {
+ this.importRestrictionInclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ImportRestrictionExclude)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() == 0) {
+ this.importRestrictionExclude = null;
+ } else {
+ this.importRestrictionExclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ExportRestrictionInclude)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() == 0) {
+ this.exportRestrictionInclude = null;
+ } else {
+ this.exportRestrictionInclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+ }
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ExportRestrictionExclude)) != null) {
+ if (optionValue instanceof String) {
+ String stringValue = (String) optionValue;
+ if (stringValue.length() == 0) {
+ this.exportRestrictionExclude = null;
+ } else {
+ this.exportRestrictionExclude = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+ }
+ }
+ }
if ((optionValue = optionsMap.get(OPTION_InlineJsr)) != null) {
- if (ENABLED.equals(optionValue)) {
- this.inlineJsrBytecode = true;
- } else if (DISABLED.equals(optionValue)) {
- this.inlineJsrBytecode = false;
+ if (this.targetJDK < JDK1_5) { // only optional if target < 1.5 (inlining on from 1.5 on)
+ if (ENABLED.equals(optionValue)) {
+ this.inlineJsrBytecode = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.inlineJsrBytecode = false;
+ }
}
}
if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue);
@@ -508,16 +598,23 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
if ((optionValue = optionsMap.get(OPTION_ReportEmptyStatement)) != null) updateSeverity(EmptyStatement, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportNonExternalizedStringLiteral)) != null) updateSeverity(NonExternalizedString, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportAssertIdentifier)) != null) updateSeverity(AssertUsedAsAnIdentifier, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportEnumIdentifier)) != null) updateSeverity(EnumUsedAsAnIdentifier, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportNonStaticAccessToStatic)) != null) updateSeverity(NonStaticAccessToStatic, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportIndirectStaticAccess)) != null) updateSeverity(IndirectStaticAccess, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportIncompatibleNonInheritedInterfaceMethod)) != null) updateSeverity(IncompatibleNonInheritedInterfaceMethod, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportUndocumentedEmptyBlock)) != null) updateSeverity(UndocumentedEmptyBlock, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryTypeCheck)) != null) updateSeverity(UnnecessaryTypeCheck, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryElse)) != null) updateSeverity(UnnecessaryElse, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportFinallyBlockNotCompletingNormally)) != null) updateSeverity(FinallyBlockNotCompleting, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportUnqualifiedFieldAccess)) != null) updateSeverity(UnqualifiedFieldAccess, optionValue);
if ((optionValue = optionsMap.get(OPTION_ReportNoEffectAssignment)) != null) updateSeverity(NoEffectAssignment, optionValue);
- if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryElse)) != null) updateSeverity(UnnecessaryElse, optionValue);
-
+ if ((optionValue = optionsMap.get(OPTION_ReportUnsafeTypeOperation)) != null) updateSeverity(UnsafeTypeOperation, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportFinalParameterBound)) != null) updateSeverity(FinalParameterBound, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportMissingSerialVersion)) != null) updateSeverity(MissingSerialVersion, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportForbiddenReference)) != null) updateSeverity(ForbiddenReference, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportVarargsArgumentNeedCast)) != null) updateSeverity(VarargsArgumentNeedCast, optionValue);
+ if ((optionValue = optionsMap.get(OPTION_ReportInconsistentNullCheck)) != null) updateSeverity(InconsistentNullCheck, optionValue);
+
// Javadoc options
if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
if (ENABLED.equals(optionValue)) {
@@ -542,11 +639,25 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
}
if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTags)) != null) {
if (ENABLED.equals(optionValue)) {
- this.reportInvalidJavadocTags= true;
+ this.reportInvalidJavadocTags = true;
} else if (DISABLED.equals(optionValue)) {
this.reportInvalidJavadocTags = false;
}
}
+ if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsDeprecatedRef)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.reportInvalidJavadocTagsDeprecatedRef = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.reportInvalidJavadocTagsDeprecatedRef = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsNotVisibleRef)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.reportInvalidJavadocTagsNotVisibleRef = true;
+ } else if (DISABLED.equals(optionValue)) {
+ this.reportInvalidJavadocTagsNotVisibleRef = false;
+ }
+ }
if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTags)) != null) {
updateSeverity(MissingJavadocTags, optionValue);
}
@@ -621,6 +732,8 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
buf.append("\n\t- javadoc comment support: ").append(this.docCommentSupport ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
buf.append("\n\t\t+ invalid javadoc: ").append(getSeverityString(InvalidJavadoc)); //$NON-NLS-1$
buf.append("\n\t\t+ report invalid javadoc tags: ").append(this.reportInvalidJavadocTags ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t\t\t* deprecated references: ").append(this.reportInvalidJavadocTagsDeprecatedRef ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t\t\t* not visble references: ").append(this.reportInvalidJavadocTagsNotVisibleRef ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t\t+ visibility level to report invalid javadoc tags: ").append(getVisibilityString(this.reportInvalidJavadocTagsVisibility)); //$NON-NLS-1$
buf.append("\n\t\t+ missing javadoc tags: ").append(getSeverityString(MissingJavadocTags)); //$NON-NLS-1$
buf.append("\n\t\t+ visibility level to report missing javadoc tags: ").append(getVisibilityString(this.reportMissingJavadocTagsVisibility)); //$NON-NLS-1$
@@ -648,6 +761,16 @@ public class CompilerOptions implements ProblemReasons, ProblemSeverities, Class
buf.append("\n\t- report unused parameter when overriding concrete method : ").append(this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t- report constructor/setter parameter hiding existing field : ").append(this.reportSpecialParameterHidingField ? ENABLED : DISABLED); //$NON-NLS-1$
buf.append("\n\t- inline JSR bytecode : ").append(this.inlineJsrBytecode ? ENABLED : DISABLED); //$NON-NLS-1$
+ buf.append("\n\t- unsafe type operation: ").append(getSeverityString(UnsafeTypeOperation)); //$NON-NLS-1$
+ buf.append("\n\t- final bound for type parameter: ").append(getSeverityString(FinalParameterBound)); //$NON-NLS-1$
+ buf.append("\n\t- missing serialVersionUID: ").append(getSeverityString(MissingSerialVersion)); //$NON-NLS-1$
+ buf.append("\n\t- varargs argument need cast: ").append(getSeverityString(VarargsArgumentNeedCast)); //$NON-NLS-1$
+ buf.append("\n\t- forbidden reference to type with access restriction: ").append(getSeverityString(ForbiddenReference)); //$NON-NLS-1$
+ buf.append("\n\t- import access restriction includes: ").append(this.importRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionInclude,','))); //$NON-NLS-1$ //$NON-NLS-2$
+ buf.append("\n\t- import access restriction excludes: ").append(this.importRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.importRestrictionExclude,','))); //$NON-NLS-1$ //$NON-NLS-2$
+ buf.append("\n\t- export access restriction includes: ").append(this.exportRestrictionInclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionInclude,','))); //$NON-NLS-1$ //$NON-NLS-2$
+ buf.append("\n\t- export access restriction excludes: ").append(this.exportRestrictionExclude == null ? "" : new String(CharOperation.concatWith(this.exportRestrictionExclude,','))); //$NON-NLS-1$ //$NON-NLS-2$
+ buf.append("\n\t- inconsistent null check: ").append(getSeverityString(InconsistentNullCheck)); //$NON-NLS-1$
return buf.toString();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/impl/Constant.java b/src/org/eclipse/jdt/internal/compiler/impl/Constant.java
index f82b409..3130eed 100644
--- a/src/org/eclipse/jdt/internal/compiler/impl/Constant.java
+++ b/src/org/eclipse/jdt/internal/compiler/impl/Constant.java
@@ -112,7 +112,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
// case (T_String<<4)+T_long : return NotAConstant;
// case (T_String<<4)+T_short : return NotAConstant;
// case (T_String<<4)+T_void : return NotAConstant;
- case (T_String<<4)+T_String : return this;
+ case (T_JavaLangString<<4)+T_JavaLangString : return this;
// case (T_String<<4)+T_Object : return NotAConstant;
// case (T_String<<4)+T_double : return NotAConstant;
// case (T_String<<4)+T_float : return NotAConstant;
@@ -213,7 +213,8 @@ public abstract class Constant implements TypeIds, OperatorIds {
switch (operator) {
case NOT :
return Constant.fromValue(!cst.booleanValue());
- case PLUS : return cst;
+ case PLUS :
+ return computeConstantOperationPLUS(Zero,T_int,cst,id);
case MINUS : //the two special -9223372036854775808L and -2147483648 are inlined at parseTime
switch (id){
case T_float : float f;
@@ -233,7 +234,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return Constant.fromValue(0.0d);}
break; //default case
}
- return computeConstantOperationMINUS(Zero,T_int,operator,cst,id);
+ return computeConstantOperationMINUS(Zero,T_int,cst,id);
case TWIDDLE:
switch (id){
case T_char : return Constant.fromValue(~ cst.charValue());
@@ -250,29 +251,29 @@ public abstract class Constant implements TypeIds, OperatorIds {
public static final Constant computeConstantOperation(Constant left, int leftId, int operator, Constant right, int rightId) {
switch (operator) {
- case AND : return computeConstantOperationAND (left,leftId,operator,right,rightId);
- case AND_AND : return computeConstantOperationAND_AND (left,leftId,operator,right,rightId);
- case DIVIDE : return computeConstantOperationDIVIDE (left,leftId,operator,right,rightId);
- case GREATER : return computeConstantOperationGREATER (left,leftId,operator,right,rightId);
- case GREATER_EQUAL : return computeConstantOperationGREATER_EQUAL(left,leftId,operator,right,rightId);
- case LEFT_SHIFT : return computeConstantOperationLEFT_SHIFT (left,leftId,operator,right,rightId);
- case LESS : return computeConstantOperationLESS (left,leftId,operator,right,rightId);
- case LESS_EQUAL : return computeConstantOperationLESS_EQUAL (left,leftId,operator,right,rightId);
- case MINUS : return computeConstantOperationMINUS (left,leftId,operator,right,rightId);
- case MULTIPLY : return computeConstantOperationMULTIPLY (left,leftId,operator,right,rightId);
- case OR : return computeConstantOperationOR (left,leftId,operator,right,rightId);
- case OR_OR : return computeConstantOperationOR_OR (left,leftId,operator,right,rightId);
- case PLUS : return computeConstantOperationPLUS (left,leftId,operator,right,rightId);
- case REMAINDER : return computeConstantOperationREMAINDER (left,leftId,operator,right,rightId);
- case RIGHT_SHIFT: return computeConstantOperationRIGHT_SHIFT(left,leftId,operator,right,rightId);
- case UNSIGNED_RIGHT_SHIFT: return computeConstantOperationUNSIGNED_RIGHT_SHIFT(left,leftId,operator,right,rightId);
- case XOR : return computeConstantOperationXOR (left,leftId,operator,right,rightId);
+ case AND : return computeConstantOperationAND (left,leftId,right,rightId);
+ case AND_AND : return computeConstantOperationAND_AND (left,leftId,right,rightId);
+ case DIVIDE : return computeConstantOperationDIVIDE (left,leftId,right,rightId);
+ case GREATER : return computeConstantOperationGREATER (left,leftId,right,rightId);
+ case GREATER_EQUAL : return computeConstantOperationGREATER_EQUAL(left,leftId,right,rightId);
+ case LEFT_SHIFT : return computeConstantOperationLEFT_SHIFT (left,leftId,right,rightId);
+ case LESS : return computeConstantOperationLESS (left,leftId,right,rightId);
+ case LESS_EQUAL : return computeConstantOperationLESS_EQUAL (left,leftId,right,rightId);
+ case MINUS : return computeConstantOperationMINUS (left,leftId,right,rightId);
+ case MULTIPLY : return computeConstantOperationMULTIPLY (left,leftId,right,rightId);
+ case OR : return computeConstantOperationOR (left,leftId,right,rightId);
+ case OR_OR : return computeConstantOperationOR_OR (left,leftId,right,rightId);
+ case PLUS : return computeConstantOperationPLUS (left,leftId,right,rightId);
+ case REMAINDER : return computeConstantOperationREMAINDER (left,leftId,right,rightId);
+ case RIGHT_SHIFT: return computeConstantOperationRIGHT_SHIFT(left,leftId,right,rightId);
+ case UNSIGNED_RIGHT_SHIFT: return computeConstantOperationUNSIGNED_RIGHT_SHIFT(left,leftId,right,rightId);
+ case XOR : return computeConstantOperationXOR (left,leftId,right,rightId);
default : return NotAConstant;
}
}
- public static final Constant computeConstantOperationAND(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationAND(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_boolean : return Constant.fromValue(left.booleanValue() & right.booleanValue());
@@ -325,12 +326,12 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, Constant right, int rightId) {
return Constant.fromValue(left.booleanValue() && right.booleanValue());
}
- public static final Constant computeConstantOperationDIVIDE(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationDIVIDE(Constant left, int leftId, Constant right, int rightId) {
// division by zero must be handled outside this method (error reporting)
switch (leftId){
@@ -416,7 +417,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_boolean :
@@ -500,15 +501,15 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_long: return Constant.fromValue(left.longValue() == right.longValue());
}
break;
- case T_String :
- if (rightId == T_String) {
+ case T_JavaLangString :
+ if (rightId == T_JavaLangString) {
//String are interned in th compiler==>thus if two string constant
//get to be compared, it is an equal on the vale which is done
return Constant.fromValue(((StringConstant)left).compileTimeEqual((StringConstant)right));
}
break;
case T_null :
- if (rightId == T_String) {
+ if (rightId == T_JavaLangString) {
return Constant.fromValue(false);
} else {
if (rightId == T_null) {
@@ -520,7 +521,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return Constant.fromValue(false);
}
- public static final Constant computeConstantOperationGREATER(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationGREATER(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -605,7 +606,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -690,7 +691,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -743,7 +744,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationLESS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationLESS(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -828,7 +829,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -912,7 +913,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationMINUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationMINUS(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -997,7 +998,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -1081,7 +1082,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationOR(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_boolean : return Constant.fromValue(left.booleanValue() | right.booleanValue());
@@ -1135,20 +1136,20 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, Constant right, int rightId) {
return Constant.fromValue(left.booleanValue() || right.booleanValue());
}
- public static final Constant computeConstantOperationPLUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationPLUS(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
- case T_Object :
- if (rightId == T_String) {
+ case T_JavaLangObject :
+ if (rightId == T_JavaLangString) {
return Constant.fromValue(left.stringValue() + right.stringValue());
}
case T_boolean :
- if (rightId == T_String) {
+ if (rightId == T_JavaLangString) {
return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
@@ -1161,7 +1162,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.charValue() + right.shortValue());
case T_int: return Constant.fromValue(left.charValue() + right.intValue());
case T_long: return Constant.fromValue(left.charValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
case T_float :
@@ -1173,7 +1174,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.floatValue() + right.shortValue());
case T_int: return Constant.fromValue(left.floatValue() + right.intValue());
case T_long: return Constant.fromValue(left.floatValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
case T_double :
@@ -1185,7 +1186,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.doubleValue() + right.shortValue());
case T_int: return Constant.fromValue(left.doubleValue() + right.intValue());
case T_long: return Constant.fromValue(left.doubleValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
case T_byte :
@@ -1197,7 +1198,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.byteValue() + right.shortValue());
case T_int: return Constant.fromValue(left.byteValue() + right.intValue());
case T_long: return Constant.fromValue(left.byteValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
@@ -1210,7 +1211,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.shortValue() + right.shortValue());
case T_int: return Constant.fromValue(left.shortValue() + right.intValue());
case T_long: return Constant.fromValue(left.shortValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
case T_int :
@@ -1222,7 +1223,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.intValue() + right.shortValue());
case T_int: return Constant.fromValue(left.intValue() + right.intValue());
case T_long: return Constant.fromValue(left.intValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
case T_long :
@@ -1234,10 +1235,10 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.longValue() + right.shortValue());
case T_int: return Constant.fromValue(left.longValue() + right.intValue());
case T_long: return Constant.fromValue(left.longValue() + right.longValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
- case T_String :
+ case T_JavaLangString :
switch (rightId){
case T_char : return Constant.fromValue(left.stringValue() + right.stringValue());
case T_float: return Constant.fromValue(left.stringValue() + right.stringValue());
@@ -1246,7 +1247,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.stringValue() + right.stringValue());
case T_int: return Constant.fromValue(left.stringValue() + right.stringValue());
case T_long: return Constant.fromValue(left.stringValue() + right.stringValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
case T_boolean: return Constant.fromValue(left.stringValue() + right.stringValue());
}
break;
@@ -1259,7 +1260,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_short: return Constant.fromValue(left.stringValue() + right.stringValue());
case T_int: return Constant.fromValue(left.stringValue() + right.stringValue());
case T_long: return Constant.fromValue(left.stringValue() + right.stringValue());
- case T_String: return Constant.fromValue(left.stringValue() + right.stringValue());
+ case T_JavaLangString: return Constant.fromValue(left.stringValue() + right.stringValue());
}
}
@@ -1267,7 +1268,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -1352,7 +1353,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -1405,7 +1406,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_char :
@@ -1458,7 +1459,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
return NotAConstant;
}
- public static final Constant computeConstantOperationXOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ public static final Constant computeConstantOperationXOR(Constant left, int leftId, Constant right, int rightId) {
switch (leftId){
case T_boolean : return Constant.fromValue(left.booleanValue() ^ right.booleanValue());
@@ -1603,7 +1604,7 @@ public abstract class Constant implements TypeIds, OperatorIds {
case T_double : return "double"; //$NON-NLS-1$
case T_boolean : return "boolean"; //$NON-NLS-1$
case T_long : return "long";//$NON-NLS-1$
- case T_String : return "java.lang.String"; //$NON-NLS-1$
+ case T_JavaLangString : return "java.lang.String"; //$NON-NLS-1$
case T_null : return "null"; //$NON-NLS-1$
default: return "unknown"; //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java b/src/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
index 52398d0..9ae827d 100644
--- a/src/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
+++ b/src/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.impl;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
@@ -20,12 +21,12 @@ public interface ITypeRequestor {
/**
* Accept the resolved binary form for the requested type.
*/
- void accept(IBinaryType binaryType, PackageBinding packageBinding);
+ void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction);
/**
* Accept the requested type's compilation unit.
*/
- void accept(ICompilationUnit unit);
+ void accept(ICompilationUnit unit, AccessRestriction accessRestriction);
/**
* Accept the unresolved source forms for the requested type.
@@ -33,5 +34,5 @@ public interface ITypeRequestor {
* contains multiple types. The first one is then guaranteed to be the one corresponding to the
* requested type.
*/
- void accept(ISourceType[] sourceType, PackageBinding packageBinding);
+ void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/impl/StringConstant.java b/src/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
index 0248540..51ab819 100644
--- a/src/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
+++ b/src/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
@@ -43,6 +43,6 @@ public String toString(){
return "(String)\"" + value +"\""; } //$NON-NLS-2$ //$NON-NLS-1$
public int typeID() {
- return T_String;
+ return T_JavaLangString;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index da45684..541002b 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -20,19 +21,56 @@ public final class ArrayBinding extends TypeBinding {
public TypeBinding leafComponentType;
public int dimensions;
-
+ LookupEnvironment environment;
char[] constantPoolName;
-public ArrayBinding(TypeBinding type, int dimensions) {
+ char[] genericTypeSignature;
+
+public ArrayBinding(TypeBinding type, int dimensions, LookupEnvironment environment) {
this.tagBits |= IsArrayType;
this.leafComponentType = type;
this.dimensions = dimensions;
+ this.environment = environment;
+ if (type instanceof UnresolvedReferenceBinding)
+ ((UnresolvedReferenceBinding) type).addWrapper(this);
+ else
+ this.tagBits |= type.tagBits & (HasTypeVariable | HasDirectWildcard);
+}
+
+public int kind() {
+ return ARRAY_TYPE;
+}
+
+/**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+ if (otherType.isArrayType()) {
+ int otherDim = otherType.dimensions();
+ if (otherDim == this.dimensions) {
+ this.leafComponentType.collectSubstitutes(otherType.leafComponentType(), substitutes);
+ } else if (otherDim > this.dimensions) {
+ ArrayBinding otherReducedType = this.environment.createArrayType(otherType.leafComponentType(), otherDim - this.dimensions);
+ this.leafComponentType.collectSubstitutes(otherReducedType, substitutes);
+ }
+ }
}
+
+/*
+ * brakets leafUniqueKey
+ * p.X[][] --> [[Lp/X;
+ */
+public char[] computeUniqueKey() {
+ char[] brackets = new char[dimensions];
+ for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
+ return CharOperation.concat(brackets, this.leafComponentType.computeUniqueKey());
+ }
+
/**
* Answer the receiver's constant pool name.
* NOTE: This method should only be used during/after code gen.
* e.g. '[Ljava/lang/Object;'
*/
-
public char[] constantPoolName() {
if (constantPoolName != null)
return constantPoolName;
@@ -41,7 +79,7 @@ public char[] constantPoolName() {
for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
return constantPoolName = CharOperation.concat(brackets, leafComponentType.signature());
}
-String debugName() {
+public String debugName() {
StringBuffer brackets = new StringBuffer(dimensions * 2);
for (int i = dimensions; --i >= 0;)
brackets.append("[]"); //$NON-NLS-1$
@@ -56,16 +94,41 @@ public int dimensions() {
* When the receiver's dimension size is one then answer the leaf component type.
*/
-public TypeBinding elementsType(Scope scope) {
- if (dimensions == 1) return leafComponentType;
- return scope.createArray(leafComponentType, dimensions - 1);
+public TypeBinding elementsType() {
+ if (this.dimensions == 1) return this.leafComponentType;
+ return this.environment.createArrayType(this.leafComponentType, this.dimensions - 1);
}
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+ */
+public TypeBinding erasure() {
+ TypeBinding erasedType = this.leafComponentType.erasure();
+ if (this.leafComponentType != erasedType)
+ return this.environment.createArrayType(erasedType, this.dimensions);
+ return this;
+}
+public LookupEnvironment environment() {
+ return this.environment;
+}
+
+public char[] genericTypeSignature() {
+
+ if (this.genericTypeSignature == null) {
+ char[] brackets = new char[dimensions];
+ for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
+ this.genericTypeSignature = CharOperation.concat(brackets, leafComponentType.genericTypeSignature());
+ }
+ return this.genericTypeSignature;
+}
+
public PackageBinding getPackage() {
return leafComponentType.getPackage();
}
+public int hashCode() {
+ return this.leafComponentType == null ? super.hashCode() : this.leafComponentType.hashCode();
+}
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
-
public boolean isCompatibleWith(TypeBinding right) {
if (this == right)
return true;
@@ -81,6 +144,9 @@ public boolean isCompatibleWith(TypeBinding right) {
} else {
if (right.isBaseType())
return false;
+ if (right.isWildcard()) {
+ return ((WildcardBinding) right).boundCheck(this);
+ }
}
//Check dimensions - Java does not support explicitly sized dimensions for types.
//However, if it did, the type checking support would go here.
@@ -143,6 +209,12 @@ public char[] sourceName() {
}
return CharOperation.concat(leafComponentType.sourceName(), brackets);
}
+public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+ if (this.leafComponentType == unresolvedType) {
+ this.leafComponentType = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+ this.tagBits |= this.leafComponentType.tagBits & (HasTypeVariable | HasDirectWildcard);
+ }
+}
public String toString() {
return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java b/src/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
index b1ec5eb..a6e82bf 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
@@ -11,14 +11,14 @@
package org.eclipse.jdt.internal.compiler.lookup;
public interface BaseTypes {
- final BaseTypeBinding IntBinding = new BaseTypeBinding(TypeIds.T_int, "int".toCharArray(), new char[] {'I'}); //$NON-NLS-1$
- final BaseTypeBinding ByteBinding = new BaseTypeBinding(TypeIds.T_byte, "byte".toCharArray(), new char[] {'B'}); //$NON-NLS-1$
- final BaseTypeBinding ShortBinding = new BaseTypeBinding(TypeIds.T_short, "short".toCharArray(), new char[] {'S'}); //$NON-NLS-1$
- final BaseTypeBinding CharBinding = new BaseTypeBinding(TypeIds.T_char, "char".toCharArray(), new char[] {'C'}); //$NON-NLS-1$
- final BaseTypeBinding LongBinding = new BaseTypeBinding(TypeIds.T_long, "long".toCharArray(), new char[] {'J'}); //$NON-NLS-1$
- final BaseTypeBinding FloatBinding = new BaseTypeBinding(TypeIds.T_float, "float".toCharArray(), new char[] {'F'}); //$NON-NLS-1$
- final BaseTypeBinding DoubleBinding = new BaseTypeBinding(TypeIds.T_double, "double".toCharArray(), new char[] {'D'}); //$NON-NLS-1$
- final BaseTypeBinding BooleanBinding = new BaseTypeBinding(TypeIds.T_boolean, "boolean".toCharArray(), new char[] {'Z'}); //$NON-NLS-1$
- final BaseTypeBinding NullBinding = new BaseTypeBinding(TypeIds.T_null, "null".toCharArray(), new char[] {'N'}); //N stands for null even if it is never internally used //$NON-NLS-1$
- final BaseTypeBinding VoidBinding = new BaseTypeBinding(TypeIds.T_void, "void".toCharArray(), new char[] {'V'}); //$NON-NLS-1$
+ final BaseTypeBinding IntBinding = new BaseTypeBinding(TypeIds.T_int, TypeConstants.INT, new char[] {'I'}); //$NON-NLS-1$
+ final BaseTypeBinding ByteBinding = new BaseTypeBinding(TypeIds.T_byte, TypeConstants.BYTE, new char[] {'B'}); //$NON-NLS-1$
+ final BaseTypeBinding ShortBinding = new BaseTypeBinding(TypeIds.T_short, TypeConstants.SHORT, new char[] {'S'}); //$NON-NLS-1$
+ final BaseTypeBinding CharBinding = new BaseTypeBinding(TypeIds.T_char, TypeConstants.CHAR, new char[] {'C'}); //$NON-NLS-1$
+ final BaseTypeBinding LongBinding = new BaseTypeBinding(TypeIds.T_long, TypeConstants.LONG, new char[] {'J'}); //$NON-NLS-1$
+ final BaseTypeBinding FloatBinding = new BaseTypeBinding(TypeIds.T_float, TypeConstants.FLOAT, new char[] {'F'}); //$NON-NLS-1$
+ final BaseTypeBinding DoubleBinding = new BaseTypeBinding(TypeIds.T_double, TypeConstants.DOUBLE, new char[] {'D'}); //$NON-NLS-1$
+ final BaseTypeBinding BooleanBinding = new BaseTypeBinding(TypeIds.T_boolean, TypeConstants.BOOLEAN, new char[] {'Z'}); //$NON-NLS-1$
+ final BaseTypeBinding NullBinding = new BaseTypeBinding(TypeIds.T_null, TypeConstants.NULL, new char[] {'N'}); //N stands for null even if it is never internally used //$NON-NLS-1$
+ final BaseTypeBinding VoidBinding = new BaseTypeBinding(TypeIds.T_void, TypeConstants.VOID, new char[] {'V'}); //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 6ada2f8..6d837a5 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -10,12 +10,15 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.ArrayList;
+
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
/*
@@ -30,16 +33,72 @@ null is NOT a valid value for a non-public field... it just means the field is n
*/
public final class BinaryTypeBinding extends ReferenceBinding {
- // all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
- private ReferenceBinding superclass;
- private ReferenceBinding enclosingType;
- private ReferenceBinding[] superInterfaces;
- private FieldBinding[] fields;
- private MethodBinding[] methods;
- private ReferenceBinding[] memberTypes;
-
- // For the link with the principle structure
- private LookupEnvironment environment;
+
+// all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
+private ReferenceBinding superclass;
+private ReferenceBinding enclosingType;
+private ReferenceBinding[] superInterfaces;
+private FieldBinding[] fields;
+private MethodBinding[] methods;
+private ReferenceBinding[] memberTypes;
+protected TypeVariableBinding[] typeVariables;
+
+// For the link with the principle structure
+private LookupEnvironment environment;
+
+public static ReferenceBinding resolveType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
+ if (type instanceof UnresolvedReferenceBinding)
+ return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
+ if (type.isParameterizedType())
+ return ((ParameterizedTypeBinding) type).resolve();
+ if (type.isWildcard())
+ return ((WildcardBinding) type).resolve();
+
+ if (convertGenericToRawType && type.isGenericType()) // raw reference to generic ?
+ return environment.createRawType(type, type.enclosingType());
+ return type;
+}
+public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, ParameterizedTypeBinding parameterizedType, int rank) {
+ switch (type.kind()) {
+
+ case Binding.PARAMETERIZED_TYPE :
+ return ((ParameterizedTypeBinding) type).resolve();
+
+ case Binding.WILDCARD_TYPE :
+ return ((WildcardBinding) type).resolve();
+
+ case Binding.ARRAY_TYPE :
+ resolveType(((ArrayBinding) type).leafComponentType, environment, parameterizedType, rank);
+ break;
+
+ case Binding.TYPE_PARAMETER :
+ ((TypeVariableBinding) type).resolve(environment);
+ break;
+
+ case Binding.GENERIC_TYPE :
+ if (parameterizedType == null) // raw reference to generic ?
+ return environment.createRawType((ReferenceBinding) type, type.enclosingType());
+ break;
+
+ default:
+ if (type instanceof UnresolvedReferenceBinding)
+ return ((UnresolvedReferenceBinding) type).resolve(environment, parameterizedType == null);
+ }
+ return type;
+}
+// resolve hierarchy types in 2 steps by first resolving any UnresolvedTypes
+static ReferenceBinding resolveUnresolvedType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
+ if (type instanceof UnresolvedReferenceBinding)
+ return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
+
+ if (type.isParameterizedType())
+ resolveUnresolvedType(((ParameterizedTypeBinding) type).type, environment, false); // still part of parameterized type ref
+ else if (type.isWildcard())
+ resolveType(((WildcardBinding) type).genericType, environment, null, 0);
+ return type;
+}
+
+
public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
this.compoundName = CharOperation.splitOn('/', binaryType.getName());
computeId();
@@ -49,6 +108,11 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType,
this.fPackage = packageBinding;
this.fileName = binaryType.getFileName();
+ char[] typeSignature = environment.options.sourceLevel >= ClassFileConstants.JDK1_5 ? binaryType.getGenericSignature() : null;
+ this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == '<'
+ ? null // is initialized in cachePartsFrom (called from LookupEnvironment.createBinaryTypeFrom())... must set to null so isGenericType() answers true
+ : NoTypeVariables;
+
// source name must be one name without "$".
char[] possibleSourceName = this.compoundName[this.compoundName.length - 1];
int start = CharOperation.lastIndexOf('$', possibleSourceName) + 1;
@@ -60,7 +124,7 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType,
}
this.modifiers = binaryType.getModifiers();
- if (binaryType.isInterface())
+ if (binaryType.getKind() == IGenericType.INTERFACE_DECL)
this.modifiers |= AccInterface;
if (binaryType.isAnonymous()) {
@@ -108,28 +172,85 @@ public MethodBinding[] availableMethods() {
return availableMethods;
}
+public int kind() {
+ if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
+ return Binding.TYPE;
+}
+
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
-
// default initialization for super-interfaces early, in case some aborting compilation error occurs,
// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
+ this.typeVariables = NoTypeVariables;
this.superInterfaces = NoSuperInterfaces;
-
- char[] superclassName = binaryType.getSuperclassName();
- if (superclassName != null)
- // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
- this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1);
+ // need enclosing type to access type variables
char[] enclosingTypeName = binaryType.getEnclosingTypeName();
if (enclosingTypeName != null) {
// attempt to find the enclosing type if it exists in the cache (otherwise - resolve it when requested)
- this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1);
+ this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1, true); // pretend parameterized to avoid raw
this.tagBits |= MemberTypeMask; // must be a member type not a top-level or local type
+ this.tagBits |= HasUnresolvedEnclosingType;
if (this.enclosingType().isStrictfp())
this.modifiers |= AccStrictfp;
if (this.enclosingType().isDeprecated())
this.modifiers |= AccDeprecatedImplicitly;
}
+ long sourceLevel = environment.options.sourceLevel;
+ char[] typeSignature = null;
+ if (sourceLevel >= ClassFileConstants.JDK1_5) {
+ typeSignature = binaryType.getGenericSignature();
+ this.tagBits |= binaryType.getTagBits();
+ }
+ if (typeSignature == null) {
+ char[] superclassName = binaryType.getSuperclassName();
+ if (superclassName != null) {
+ // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
+ this.superclass = environment.getTypeFromConstantPoolName(superclassName, 0, -1, false);
+ this.tagBits |= HasUnresolvedSuperclass;
+ }
+
+ this.superInterfaces = NoSuperInterfaces;
+ char[][] interfaceNames = binaryType.getInterfaceNames();
+ if (interfaceNames != null) {
+ int size = interfaceNames.length;
+ if (size > 0) {
+ this.superInterfaces = new ReferenceBinding[size];
+ for (int i = 0; i < size; i++)
+ // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+ this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false);
+ this.tagBits |= HasUnresolvedSuperinterfaces;
+ }
+ }
+ } else {
+ // ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
+ SignatureWrapper wrapper = new SignatureWrapper(typeSignature);
+ if (wrapper.signature[wrapper.start] == '<') {
+ // ParameterPart = '<' ParameterSignature(s) '>'
+ wrapper.start++; // skip '<'
+ this.typeVariables = createTypeVariables(wrapper, this);
+ wrapper.start++; // skip '>'
+ this.tagBits |= HasUnresolvedTypeVariables;
+ this.modifiers |= AccGenericSignature;
+ }
+
+ // attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
+ this.superclass = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this);
+ this.tagBits |= HasUnresolvedSuperclass;
+
+ this.superInterfaces = NoSuperInterfaces;
+ if (!wrapper.atEnd()) {
+ // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+ java.util.ArrayList types = new java.util.ArrayList(2);
+ do {
+ types.add(environment.getTypeFromTypeSignature(wrapper, NoTypeVariables, this));
+ } while (!wrapper.atEnd());
+ this.superInterfaces = new ReferenceBinding[types.size()];
+ types.toArray(this.superInterfaces);
+ this.tagBits |= HasUnresolvedSuperinterfaces;
+ }
+ }
+
this.memberTypes = NoMemberTypes;
IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
if (memberTypeStructures != null) {
@@ -138,109 +259,174 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
this.memberTypes = new ReferenceBinding[size];
for (int i = 0; i < size; i++)
// attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
- this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1);
+ this.memberTypes[i] = environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false);
+ this.tagBits |= HasUnresolvedMemberTypes;
}
}
- char[][] interfaceNames = binaryType.getInterfaceNames();
- if (interfaceNames != null) {
- int size = interfaceNames.length;
- if (size > 0) {
- this.superInterfaces = new ReferenceBinding[size];
- for (int i = 0; i < size; i++)
- // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
- this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1);
- }
- }
if (needFieldsAndMethods) {
- createFields(binaryType.getFields());
- createMethods(binaryType.getMethods());
+ createFields(binaryType.getFields(), sourceLevel);
+ createMethods(binaryType.getMethods(), sourceLevel);
} else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
this.fields = NoFields;
this.methods = NoMethods;
}
}
-private void createFields(IBinaryField[] iFields) {
+private void createFields(IBinaryField[] iFields, long sourceLevel) {
this.fields = NoFields;
if (iFields != null) {
int size = iFields.length;
if (size > 0) {
this.fields = new FieldBinding[size];
+ boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
for (int i = 0; i < size; i++) {
- IBinaryField field = iFields[i];
- this.fields[i] =
+ IBinaryField binaryField = iFields[i];
+ char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
+ TypeBinding type = fieldSignature == null
+ ? environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this)
+ : environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), NoTypeVariables, this);
+ FieldBinding field =
new FieldBinding(
- field.getName(),
- environment.getTypeFromSignature(field.getTypeName(), 0, -1),
- field.getModifiers() | AccUnresolved,
+ binaryField.getName(),
+ type,
+ binaryField.getModifiers() | AccUnresolved,
this,
- field.getConstant());
+ binaryField.getConstant());
+ field.id = i; // ordinal
+ if (use15specifics) {
+ field.tagBits |= binaryField.getTagBits();
+ }
+ this.fields[i] = field;
+
}
}
}
}
-private MethodBinding createMethod(IBinaryMethod method) {
+private MethodBinding createMethod(IBinaryMethod method, long sourceLevel) {
int methodModifiers = method.getModifiers() | AccUnresolved;
-
+ if (sourceLevel < ClassFileConstants.JDK1_5)
+ methodModifiers &= ~AccVarargs; // vararg methods are not recognized until 1.5
ReferenceBinding[] exceptions = NoExceptions;
- char[][] exceptionTypes = method.getExceptionTypeNames();
- if (exceptionTypes != null) {
- int size = exceptionTypes.length;
+ TypeBinding[] parameters = NoParameters;
+ TypeVariableBinding[] typeVars = NoTypeVariables;
+ TypeBinding returnType = null;
+
+ final boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
+ char[] methodSignature = use15specifics ? method.getGenericSignature() : null;
+ if (methodSignature == null) { // no generics
+ char[] methodDescriptor = method.getMethodDescriptor(); // of the form (I[Ljava/jang/String;)V
+ int numOfParams = 0;
+ char nextChar;
+ int index = 0; // first character is always '(' so skip it
+ while ((nextChar = methodDescriptor[++index]) != ')') {
+ if (nextChar != '[') {
+ numOfParams++;
+ if (nextChar == 'L')
+ while ((nextChar = methodDescriptor[++index]) != ';'){/*empty*/}
+ }
+ }
+
+ // Ignore synthetic argument for member types.
+ int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
+ int size = numOfParams - startIndex;
if (size > 0) {
- exceptions = new ReferenceBinding[size];
- for (int i = 0; i < size; i++)
- exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1);
+ parameters = new TypeBinding[size];
+ index = 1;
+ int end = 0; // first character is always '(' so skip it
+ for (int i = 0; i < numOfParams; i++) {
+ while ((nextChar = methodDescriptor[++end]) == '['){/*empty*/}
+ if (nextChar == 'L')
+ while ((nextChar = methodDescriptor[++end]) != ';'){/*empty*/}
+
+ if (i >= startIndex) // skip the synthetic arg if necessary
+ parameters[i - startIndex] = environment.getTypeFromSignature(methodDescriptor, index, end, false, this);
+ index = end + 1;
+ }
}
- }
- TypeBinding[] parameters = NoParameters;
- char[] methodSignature = method.getMethodDescriptor(); // of the form (I[Ljava/jang/String;)V
- int numOfParams = 0;
- char nextChar;
- int index = 0; // first character is always '(' so skip it
- while ((nextChar = methodSignature[++index]) != ')') {
- if (nextChar != '[') {
- numOfParams++;
- if (nextChar == 'L')
- while ((nextChar = methodSignature[++index]) != ';'){/*empty*/}
+ char[][] exceptionTypes = method.getExceptionTypeNames();
+ if (exceptionTypes != null) {
+ size = exceptionTypes.length;
+ if (size > 0) {
+ exceptions = new ReferenceBinding[size];
+ for (int i = 0; i < size; i++)
+ exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
+ }
}
- }
- // Ignore synthetic argument for member types.
- int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
- int size = numOfParams - startIndex;
- if (size > 0) {
- parameters = new TypeBinding[size];
- index = 1;
- int end = 0; // first character is always '(' so skip it
- for (int i = 0; i < numOfParams; i++) {
- while ((nextChar = methodSignature[++end]) == '['){/*empty*/}
- if (nextChar == 'L')
- while ((nextChar = methodSignature[++end]) != ';'){/*empty*/}
-
- if (i >= startIndex) // skip the synthetic arg if necessary
- parameters[i - startIndex] = environment.getTypeFromSignature(methodSignature, index, end);
- index = end + 1;
+ if (!method.isConstructor())
+ returnType = environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this); // index is currently pointing at the ')'
+ } else {
+ // MethodTypeSignature = ParameterPart(optional) '(' TypeSignatures ')' return_typeSignature ['^' TypeSignature (optional)]
+ SignatureWrapper wrapper = new SignatureWrapper(methodSignature);
+ if (wrapper.signature[wrapper.start] == '<') {
+ // (Ljava/lang/Class;)TA;
+ // ParameterPart = '<' ParameterSignature(s) '>'
+ wrapper.start++; // skip '<'
+ typeVars = createTypeVariables(wrapper, this);
+ wrapper.start++; // skip '>'
+ }
+
+ if (wrapper.signature[wrapper.start] == '(') {
+ wrapper.start++; // skip '('
+ if (wrapper.signature[wrapper.start] == ')') {
+ wrapper.start++; // skip ')'
+ } else {
+ java.util.ArrayList types = new java.util.ArrayList(2);
+ int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
+ if (startIndex == 1)
+ environment.getTypeFromTypeSignature(wrapper, typeVars, this); // skip synthetic argument
+ while (wrapper.signature[wrapper.start] != ')') {
+ types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
+ }
+ wrapper.start++; // skip ')'
+ parameters = new TypeBinding[types.size()];
+ types.toArray(parameters);
+ }
+ }
+
+ if (!method.isConstructor())
+ returnType = environment.getTypeFromTypeSignature(wrapper, typeVars, this);
+
+ if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^') {
+ // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+ java.util.ArrayList types = new java.util.ArrayList(2);
+ do {
+ wrapper.start++; // skip '^'
+ types.add(environment.getTypeFromTypeSignature(wrapper, typeVars, this));
+ } while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == '^');
+ exceptions = new ReferenceBinding[types.size()];
+ types.toArray(exceptions);
+ } else { // get the exceptions the old way
+ char[][] exceptionTypes = method.getExceptionTypeNames();
+ if (exceptionTypes != null) {
+ int size = exceptionTypes.length;
+ if (size > 0) {
+ exceptions = new ReferenceBinding[size];
+ for (int i = 0; i < size; i++)
+ exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false);
+ }
+ }
}
}
- MethodBinding binding = null;
- if (method.isConstructor())
- binding = new MethodBinding(methodModifiers, parameters, exceptions, this);
- else
- binding = new MethodBinding(
- methodModifiers,
- method.getSelector(),
- environment.getTypeFromSignature(methodSignature, index + 1, -1), // index is currently pointing at the ')'
- parameters,
- exceptions,
- this);
- return binding;
+ MethodBinding result = method.isConstructor()
+ ? new MethodBinding(methodModifiers, parameters, exceptions, this)
+ : new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
+ if (use15specifics) {
+ result.tagBits |= method.getTagBits();
+ }
+ result.typeVariables = typeVars;
+ // fixup the declaring element of the type variable
+ for (int i = 0, length = typeVars.length; i < length; i++) {
+ typeVars[i].declaringElement = result;
+ }
+ return result;
}
/**
* Create method bindings for binary type, filtering out and synthetics
*/
-private void createMethods(IBinaryMethod[] iMethods) {
+private void createMethods(IBinaryMethod[] iMethods, long sourceLevel) {
int total = 0, initialTotal = 0, iClinit = -1;
int[] toSkip = null;
if (iMethods != null) {
@@ -270,25 +456,71 @@ private void createMethods(IBinaryMethod[] iMethods) {
this.methods = new MethodBinding[total];
if (total == initialTotal) {
for (int i = 0; i < initialTotal; i++)
- this.methods[i] = createMethod(iMethods[i]);
+ this.methods[i] = createMethod(iMethods[i], sourceLevel);
} else {
for (int i = 0, index = 0; i < initialTotal; i++)
if (iClinit != i && (toSkip == null || toSkip[i] != -1))
- this.methods[index++] = createMethod(iMethods[i]);
+ this.methods[index++] = createMethod(iMethods[i], sourceLevel);
}
modifiers |= AccUnresolved; // until methods() is sent
}
+
+private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, Binding declaringElement) {
+ // detect all type variables first
+ char[] typeSignature = wrapper.signature;
+ int depth = 0, length = typeSignature.length;
+ int rank = 0;
+ ArrayList variables = new ArrayList(1);
+ depth = 0;
+ boolean pendingVariable = true;
+ createVariables: {
+ for (int i = 1; i < length; i++) {
+ switch(typeSignature[i]) {
+ case '<' :
+ depth++;
+ break;
+ case '>' :
+ if (--depth < 0)
+ break createVariables;
+ break;
+ case ';' :
+ if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != ':'))
+ pendingVariable = true;
+ break;
+ default:
+ if (pendingVariable) {
+ pendingVariable = false;
+ int colon = CharOperation.indexOf(':', typeSignature, i);
+ char[] variableName = CharOperation.subarray(typeSignature, i, colon);
+ variables.add(new TypeVariableBinding(variableName, declaringElement, rank++));
+ }
+ }
+ }
+ }
+ // initialize type variable bounds - may refer to forward variables
+ TypeVariableBinding[] result;
+ variables.toArray(result = new TypeVariableBinding[rank]);
+ for (int i = 0; i < rank; i++) {
+ initializeTypeVariable(result[i], result, wrapper);
+ }
+ return result;
+}
+
/* Answer the receiver's enclosing type... null if the receiver is a top level type.
*
* NOTE: enclosingType of a binary type is resolved when needed
*/
public ReferenceBinding enclosingType() {
- if (enclosingType == null)
- return null;
- if (enclosingType instanceof UnresolvedReferenceBinding)
- enclosingType = ((UnresolvedReferenceBinding) enclosingType).resolve(environment);
- return enclosingType;
+ if ((this.tagBits & HasUnresolvedEnclosingType) == 0)
+ return this.enclosingType;
+
+ this.enclosingType = resolveUnresolvedType(this.enclosingType, this.environment, false); // no raw conversion for now
+ this.tagBits &= ~HasUnresolvedEnclosingType;
+
+ // finish resolving the type
+ this.enclosingType = resolveType(this.enclosingType, this.environment, false);
+ return this.enclosingType;
}
// NOTE: the type of each field of a binary type is resolved when needed
@@ -297,13 +529,15 @@ public FieldBinding[] fields() {
resolveTypeFor(fields[i]);
return fields;
}
+public long getAnnotationTagBits() {
+ return this.tagBits;
+}
// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
-
public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
int argCount = argumentTypes.length;
nextMethod : for (int m = methods.length; --m >= 0;) {
MethodBinding method = methods[m];
- if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
+ if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
resolveTypesFor(method);
TypeBinding[] toMatch = method.parameters;
for (int p = 0; p < argCount; p++)
@@ -317,7 +551,8 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
// searches up the hierarchy as long as no potential (but not exact) match was found.
-public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+ // sender from refScope calls recordTypeReference(this)
int argCount = argumentTypes.length;
int selectorLength = selector.length;
boolean foundNothing = true;
@@ -338,10 +573,15 @@ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes
if (foundNothing) {
if (isInterface()) {
- if (superInterfaces.length == 1)
- return superInterfaces[0].getExactMethod(selector, argumentTypes);
+ if (superInterfaces.length == 1) {
+ if (refScope != null)
+ refScope.recordTypeReference(superInterfaces[0]);
+ return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+ }
} else if (superclass != null) {
- return superclass.getExactMethod(selector, argumentTypes);
+ if (refScope != null)
+ refScope.recordTypeReference(superclass);
+ return superclass.getExactMethod(selector, argumentTypes, refScope);
}
}
return null;
@@ -368,7 +608,7 @@ public ReferenceBinding getMemberType(char[] typeName) {
int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
- return this.memberTypes[i] = ((UnresolvedReferenceBinding) memberType).resolve(environment);
+ return this.memberTypes[i] = resolveType(memberType, this.environment, false); // no raw conversion for now
} else if (CharOperation.equals(typeName, memberType.sourceName)) {
return memberType;
}
@@ -408,11 +648,81 @@ public boolean hasMemberTypes() {
}
// NOTE: member types of binary types are resolved when needed
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+ TypeVariableBinding variable = super.getTypeVariable(variableName);
+ variable.resolve(this.environment);
+ return variable;
+}
+private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper) {
+ // ParameterSignature = Identifier ':' TypeSignature
+ // or Identifier ':' TypeSignature(optional) InterfaceBound(s)
+ // InterfaceBound = ':' TypeSignature
+ int colon = CharOperation.indexOf(':', wrapper.signature, wrapper.start);
+ wrapper.start = colon + 1; // skip name + ':'
+ ReferenceBinding type, firstBound = null;
+ if (wrapper.signature[wrapper.start] == ':') {
+ type = environment.getType(JAVA_LANG_OBJECT);
+ } else {
+ type = (ReferenceBinding) environment.getTypeFromTypeSignature(wrapper, existingVariables, this);
+ firstBound = type;
+ }
+
+ // variable is visible to its bounds
+ variable.modifiers |= AccUnresolved;
+ variable.superclass = type;
+
+ ReferenceBinding[] bounds = null;
+ if (wrapper.signature[wrapper.start] == ':') {
+ java.util.ArrayList types = new java.util.ArrayList(2);
+ do {
+ wrapper.start++; // skip ':'
+ types.add(environment.getTypeFromTypeSignature(wrapper, existingVariables, this));
+ } while (wrapper.signature[wrapper.start] == ':');
+ bounds = new ReferenceBinding[types.size()];
+ types.toArray(bounds);
+ }
+
+ variable.superInterfaces = bounds == null ? NoSuperInterfaces : bounds;
+ if (firstBound == null) {
+ firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
+ variable.modifiers |= AccInterface;
+ }
+ variable.firstBound = firstBound;
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+
+ if (this == otherType) return true;
+ if (otherType == null) return false;
+ switch(otherType.kind()) {
+
+ case Binding.WILDCARD_TYPE :
+ return ((WildcardBinding) otherType).boundCheck(this);
+
+ case Binding.RAW_TYPE :
+ return otherType.erasure() == this;
+ }
+ return false;
+}
+public boolean isGenericType() {
+ return this.typeVariables != NoTypeVariables;
+}
+// NOTE: member types of binary types are resolved when needed
+
public ReferenceBinding[] memberTypes() {
- for (int i = memberTypes.length; --i >= 0;)
- if (memberTypes[i] instanceof UnresolvedReferenceBinding)
- memberTypes[i] = ((UnresolvedReferenceBinding) memberTypes[i]).resolve(environment);
- return memberTypes;
+ if ((this.tagBits & HasUnresolvedMemberTypes) == 0)
+ return this.memberTypes;
+
+ for (int i = this.memberTypes.length; --i >= 0;)
+ this.memberTypes[i] = resolveUnresolvedType(this.memberTypes[i], this.environment, false); // no raw conversion for now
+ this.tagBits &= ~HasUnresolvedMemberTypes;
+
+ for (int i = this.memberTypes.length; --i >= 0;)
+ this.memberTypes[i] = resolveType(this.memberTypes[i], this.environment, false); // no raw conversion for now
+ return this.memberTypes;
}
// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
@@ -422,62 +732,71 @@ public MethodBinding[] methods() {
for (int i = methods.length; --i >= 0;)
resolveTypesFor(methods[i]);
- modifiers ^= AccUnresolved;
+ modifiers &= ~AccUnresolved;
return methods;
}
-TypeBinding resolveType(TypeBinding type) {
- if (type instanceof UnresolvedReferenceBinding)
- return ((UnresolvedReferenceBinding) type).resolve(environment);
- if (type instanceof ArrayBinding) {
- ArrayBinding array = (ArrayBinding) type;
- if (array.leafComponentType instanceof UnresolvedReferenceBinding)
- array.leafComponentType = ((UnresolvedReferenceBinding) array.leafComponentType).resolve(environment);
- }
- return type;
-}
private FieldBinding resolveTypeFor(FieldBinding field) {
- if ((field.modifiers & AccUnresolved) != 0) {
- field.type = resolveType(field.type);
- field.modifiers ^= AccUnresolved;
- }
+ if ((field.modifiers & AccUnresolved) == 0)
+ return field;
+
+ field.type = resolveType(field.type, this.environment, null, 0);
+ field.modifiers &= ~AccUnresolved;
return field;
}
-private MethodBinding resolveTypesFor(MethodBinding method) {
+MethodBinding resolveTypesFor(MethodBinding method) {
if ((method.modifiers & AccUnresolved) == 0)
return method;
if (!method.isConstructor())
- method.returnType = resolveType(method.returnType);
+ method.returnType = resolveType(method.returnType, this.environment, null, 0);
for (int i = method.parameters.length; --i >= 0;)
- method.parameters[i] = resolveType(method.parameters[i]);
+ method.parameters[i] = resolveType(method.parameters[i], this.environment, null, 0);
for (int i = method.thrownExceptions.length; --i >= 0;)
- if (method.thrownExceptions[i] instanceof UnresolvedReferenceBinding)
- method.thrownExceptions[i] = ((UnresolvedReferenceBinding) method.thrownExceptions[i]).resolve(environment);
- method.modifiers ^= AccUnresolved;
+ method.thrownExceptions[i] = resolveType(method.thrownExceptions[i], this.environment, true);
+ for (int i = method.typeVariables.length; --i >= 0;)
+ method.typeVariables[i].resolve(this.environment);
+ method.modifiers &= ~AccUnresolved;
return method;
}
+
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
*
* NOTE: superclass of a binary type is resolved when needed
*/
public ReferenceBinding superclass() {
- if (superclass == null)
- return null;
- if (superclass instanceof UnresolvedReferenceBinding)
- superclass = ((UnresolvedReferenceBinding) superclass).resolve(environment);
- return superclass;
+ if ((this.tagBits & HasUnresolvedSuperclass) == 0)
+ return this.superclass;
+
+ this.superclass = resolveUnresolvedType(this.superclass, this.environment, true);
+ this.tagBits &= ~HasUnresolvedSuperclass;
+
+ // finish resolving the type
+ this.superclass = resolveType(this.superclass, this.environment, true);
+ return this.superclass;
}
// NOTE: superInterfaces of binary types are resolved when needed
public ReferenceBinding[] superInterfaces() {
- for (int i = superInterfaces.length; --i >= 0;)
- if (superInterfaces[i] instanceof UnresolvedReferenceBinding)
- superInterfaces[i] = ((UnresolvedReferenceBinding) superInterfaces[i]).resolve(environment);
- return superInterfaces;
+ if ((this.tagBits & HasUnresolvedSuperinterfaces) == 0)
+ return this.superInterfaces;
+
+ for (int i = this.superInterfaces.length; --i >= 0;)
+ this.superInterfaces[i] = resolveUnresolvedType(this.superInterfaces[i], this.environment, true);
+ this.tagBits &= ~HasUnresolvedSuperinterfaces;
+
+ for (int i = this.superInterfaces.length; --i >= 0;)
+ this.superInterfaces[i] = resolveType(this.superInterfaces[i], this.environment, true);
+ return this.superInterfaces;
}
-MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
- return methods;
+public TypeVariableBinding[] typeVariables() {
+ if ((this.tagBits & HasUnresolvedTypeVariables) == 0)
+ return this.typeVariables;
+
+ for (int i = this.typeVariables.length; --i >= 0;)
+ this.typeVariables[i].resolve(this.environment);
+ this.tagBits &= ~HasUnresolvedTypeVariables;
+ return this.typeVariables;
}
public String toString() {
String s = ""; //$NON-NLS-1$
@@ -547,4 +866,7 @@ public String toString() {
s += "\n\n\n"; //$NON-NLS-1$
return s;
}
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+ return methods;
+}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/src/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index d6225aa..226f46f 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -10,18 +10,49 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
-public abstract class Binding implements BindingIds, CompilerModifiers, ProblemReasons {
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
+public abstract class Binding implements CompilerModifiers, ProblemReasons {
+
+ // binding kinds
+ public static final int FIELD = ASTNode.Bit1;
+ public static final int LOCAL = ASTNode.Bit2;
+ public static final int VARIABLE = FIELD | LOCAL;
+ public static final int TYPE = ASTNode.Bit3;
+ public static final int METHOD = ASTNode.Bit4;
+ public static final int PACKAGE = ASTNode.Bit5;
+ public static final int IMPORT = ASTNode.Bit6;
+ public static final int ARRAY_TYPE = TYPE | ASTNode.Bit7;
+ public static final int PARAMETERIZED_TYPE = TYPE | ASTNode.Bit8;
+ public static final int WILDCARD_TYPE = TYPE | ASTNode.Bit9;
+ public static final int RAW_TYPE = TYPE | ASTNode.Bit10;
+ public static final int GENERIC_TYPE = TYPE | ASTNode.Bit11;
+ public static final int TYPE_PARAMETER = TYPE | ASTNode.Bit12;
+ public static final int ANNOTATION_BINDING = TYPE | ASTNode.Bit13; // for annotation refs
+
/* API
* Answer the receiver's binding type from Binding.BindingID.
*
* Note: Do NOT expect this to be used very often... only in switch statements with
* more than 2 possible choices.
*/
- public abstract int bindingType();
+ public abstract int kind();
+ /*
+ * Computes a key that uniquely identifies this binding.
+ * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding or a PackageBinding.
+ */
+ public char[] computeUniqueKey() {
+ return null;
+ }
+
+ public long getAnnotationTagBits() {
+ // TODO (philippe) need to generalize to methods & fields
+ return 0;
+ }
+
/* API
* Answer true if the receiver is not a problem binding
*/
-
public final boolean isValidBinding() {
return problemId() == NoError;
}
@@ -29,14 +60,13 @@ public abstract class Binding implements BindingIds, CompilerModifiers, ProblemR
* Answer the problem id associated with the receiver.
* NoError if the receiver is a valid binding.
*/
-
+ // TODO (philippe) should rename into problemReason()
public int problemId() {
return NoError;
}
/* Answer a printable representation of the receiver.
*/
public abstract char[] readableName();
-
/* Shorter printable representation of the receiver (no qualified type)
*/
public char[] shortReadableName(){
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/src/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index f0f9451..50a15c7 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -14,7 +14,6 @@ import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
public class BlockScope extends Scope {
@@ -223,7 +222,7 @@ public class BlockScope extends Scope {
LocalVariableBinding local = locals[ilocal]; // if no local at all, will be locals[ilocal]==null
// check if variable is actually used, and may force it to be preserved
- boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && (local.constant == Constant.NotAConstant));
+ boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && !local.isConstantValue());
// do not report fake used variable
if (local.useFlag == LocalVariableBinding.UNUSED
@@ -319,7 +318,7 @@ public class BlockScope extends Scope {
*/
public final ReferenceBinding findLocalType(char[] name) {
- long compliance = environment().options.complianceLevel;
+ long compliance = environment().options.complianceLevel;
for (int i = 0, length = subscopeCount; i < length; i++) {
if (subscopes[i] instanceof ClassScope) {
LocalTypeBinding sourceType = (LocalTypeBinding)((ClassScope) subscopes[i]).referenceContext.binding;
@@ -377,10 +376,11 @@ public class BlockScope extends Scope {
*/
public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, boolean needResolve) {
- Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, needResolve);
+ Binding binding = getBinding(compoundName[0], mask | Binding.TYPE | Binding.PACKAGE, invocationSite, needResolve);
invocationSite.setFieldIndex(1);
if (binding instanceof VariableBinding) return binding;
- compilationUnitScope().recordSimpleReference(compoundName[0]);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordSimpleReference(compoundName[0]);
if (!binding.isValidBinding()) return binding;
int length = compoundName.length;
@@ -388,7 +388,7 @@ public class BlockScope extends Scope {
foundType : if (binding instanceof PackageBinding) {
PackageBinding packageBinding = (PackageBinding) binding;
while (currentIndex < length) {
- compilationUnitScope().recordReference(packageBinding.compoundName, compoundName[currentIndex]);
+ unitScope.recordReference(packageBinding.compoundName, compoundName[currentIndex]);
binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
invocationSite.setFieldIndex(currentIndex);
if (binding == null) {
@@ -429,7 +429,7 @@ public class BlockScope extends Scope {
char[] nextName = compoundName[currentIndex++];
invocationSite.setFieldIndex(currentIndex);
invocationSite.setActualReceiverType(typeBinding);
- if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
+ if ((mask & Binding.FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
if (!binding.isValidBinding())
return new ProblemFieldBinding(
((FieldBinding) binding).declaringClass,
@@ -438,7 +438,7 @@ public class BlockScope extends Scope {
break; // binding is now a field
}
if ((binding = findMemberType(nextName, typeBinding)) == null) {
- if ((mask & FIELD) != 0) {
+ if ((mask & Binding.FIELD) != 0) {
return new ProblemBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
typeBinding,
@@ -454,7 +454,7 @@ public class BlockScope extends Scope {
CharOperation.subarray(compoundName, 0, currentIndex),
binding.problemId());
}
- if ((mask & FIELD) != 0 && (binding instanceof FieldBinding)) {
+ if ((mask & Binding.FIELD) != 0 && (binding instanceof FieldBinding)) {
// was looking for a field and found a field
FieldBinding field = (FieldBinding) binding;
if (!field.isStatic())
@@ -464,7 +464,7 @@ public class BlockScope extends Scope {
NonStaticReferenceInStaticContext);
return binding;
}
- if ((mask & TYPE) != 0 && (binding instanceof ReferenceBinding)) {
+ if ((mask & Binding.TYPE) != 0 && (binding instanceof ReferenceBinding)) {
// was looking for a type and found a type
return binding;
}
@@ -484,7 +484,7 @@ public class BlockScope extends Scope {
Binding binding =
getBinding(
compoundName[currentIndex++],
- VARIABLE | TYPE | PACKAGE,
+ Binding.VARIABLE | Binding.TYPE | Binding.PACKAGE,
invocationSite,
true /*resolve*/);
if (!binding.isValidBinding())
@@ -638,7 +638,7 @@ public class BlockScope extends Scope {
// use 'this' if possible
if (!currentMethodScope.isConstructorCall && !currentMethodScope.isStatic) {
- if (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType))) {
+ if (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeErasingTo(targetEnclosingType) != null)) {
return EmulationPathToImplicitThis; // implicit this is good enough
}
}
@@ -658,7 +658,7 @@ public class BlockScope extends Scope {
// reject allocation and super constructor call
if (ignoreEnclosingArgInConstructorCall
&& currentMethodScope.isConstructorCall
- && (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) {
+ && (sourceType == targetEnclosingType || (!onlyExactMatch && sourceType.findSuperTypeErasingTo(targetEnclosingType) != null))) {
return NoEnclosingInstanceInConstructorCall;
}
return new Object[] { syntheticArg };
@@ -695,7 +695,7 @@ public class BlockScope extends Scope {
//done?
if (currentType == targetEnclosingType
- || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) break;
+ || (!onlyExactMatch && currentType.findSuperTypeErasingTo(targetEnclosingType) != null)) break;
if (currentMethodScope != null) {
currentMethodScope = currentMethodScope.enclosingMethodScope();
@@ -719,7 +719,7 @@ public class BlockScope extends Scope {
currentType = currentEnclosingType;
}
if (currentType == targetEnclosingType
- || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) {
+ || (!onlyExactMatch && currentType.findSuperTypeErasingTo(targetEnclosingType) != null)) {
return path;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 6d83943..82bda2d 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -11,17 +11,23 @@
package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Clinit;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
public class ClassScope extends Scope {
public TypeDeclaration referenceContext;
+ private TypeReference superTypeReference;
private final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
@@ -54,7 +60,7 @@ public class ClassScope extends Scope {
if (hierarchyIsInconsistent) { // 72468
referenceContext.binding.fields = new FieldBinding[1];
referenceContext.binding.fields[0] =
- new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+ new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
} else {
referenceContext.binding.fields = NoFields;
}
@@ -64,9 +70,13 @@ public class ClassScope extends Scope {
FieldDeclaration[] fields = referenceContext.fields;
int size = fields.length;
int count = 0;
- for (int i = 0; i < size; i++)
- if (fields[i].isField())
- count++;
+ for (int i = 0; i < size; i++) {
+ switch (fields[i].getKind()) {
+ case AbstractVariableDeclaration.FIELD:
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ count++;
+ }
+ }
if (hierarchyIsInconsistent)
count++;
@@ -77,7 +87,7 @@ public class ClassScope extends Scope {
count = 0;
for (int i = 0; i < size; i++) {
FieldDeclaration field = fields[i];
- if (!field.isField()) {
+ if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
if (referenceContext.binding.isInterface())
problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
} else {
@@ -111,7 +121,7 @@ public class ClassScope extends Scope {
}
// remove duplicate fields
if (duplicate) {
- FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
+ FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
// we know we'll be removing at least 1 duplicate name
size = count;
count = 0;
@@ -123,7 +133,7 @@ public class ClassScope extends Scope {
fieldBindings = newFieldBindings;
}
if (hierarchyIsInconsistent)
- fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+ fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, IntBinding, AccPrivate, referenceContext.binding, null);
if (count != fieldBindings.length)
System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
@@ -157,7 +167,8 @@ public class ClassScope extends Scope {
LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
referenceContext.binding = localType;
checkAndSetModifiers();
-
+ buildTypeVariables();
+
// Look at member types
ReferenceBinding[] memberTypeBindings = NoMemberTypes;
if (referenceContext.memberTypes != null) {
@@ -166,7 +177,7 @@ public class ClassScope extends Scope {
int count = 0;
nextMember : for (int i = 0; i < size; i++) {
TypeDeclaration memberContext = referenceContext.memberTypes[i];
- if (memberContext.isInterface()) {
+ if (memberContext.kind() == IGenericType.INTERFACE_DECL) {
problemReporter().nestedClassCannotDeclareInterface(memberContext);
continue nextMember;
}
@@ -186,7 +197,6 @@ public class ClassScope extends Scope {
continue nextMember;
}
}
-
ClassScope memberScope = new ClassScope(this, referenceContext.memberTypes[i]);
LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
memberBinding.setAsMemberType();
@@ -209,25 +219,76 @@ public class ClassScope extends Scope {
referenceContext.binding.verifyMethods(environment().methodVerifier());
}
+ private void buildMemberTypes(AccessRestriction accessRestriction) {
+ SourceTypeBinding sourceType = referenceContext.binding;
+ ReferenceBinding[] memberTypeBindings = NoMemberTypes;
+ if (referenceContext.memberTypes != null) {
+ int length = referenceContext.memberTypes.length;
+ memberTypeBindings = new ReferenceBinding[length];
+ int count = 0;
+ nextMember : for (int i = 0; i < length; i++) {
+ TypeDeclaration memberContext = referenceContext.memberTypes[i];
+ if (memberContext.kind() == IGenericType.INTERFACE_DECL
+ && sourceType.isNestedType()
+ && sourceType.isClass()
+ && !sourceType.isStatic()) {
+ problemReporter().nestedClassCannotDeclareInterface(memberContext);
+ continue nextMember;
+ }
+ ReferenceBinding type = sourceType;
+ // check that the member does not conflict with an enclosing type
+ do {
+ if (CharOperation.equals(type.sourceName, memberContext.name)) {
+ problemReporter().hidingEnclosingType(memberContext);
+ continue nextMember;
+ }
+ type = type.enclosingType();
+ } while (type != null);
+ // check that the member type does not conflict with another sibling member type
+ for (int j = 0; j < i; j++) {
+ if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
+ problemReporter().duplicateNestedType(memberContext);
+ continue nextMember;
+ }
+ }
+
+ ClassScope memberScope = new ClassScope(this, memberContext);
+ memberTypeBindings[count++] = memberScope.buildType(sourceType, sourceType.fPackage, accessRestriction);
+ }
+ if (count != length)
+ System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
+ }
+ sourceType.memberTypes = memberTypeBindings;
+ }
+
private void buildMethods() {
- if (referenceContext.methods == null) {
+ boolean isEnum = referenceContext.kind() == IGenericType.ENUM_DECL;
+ if (referenceContext.methods == null && !isEnum) {
referenceContext.binding.methods = NoMethods;
return;
}
// iterate the method declarations to create the bindings
AbstractMethodDeclaration[] methods = referenceContext.methods;
- int size = methods.length;
+ int size = methods == null ? 0 : methods.length;
+ // look for method
int clinitIndex = -1;
for (int i = 0; i < size; i++) {
- if (methods[i] instanceof Clinit) {
+ if (methods[i].isClinit()) {
clinitIndex = i;
break;
}
}
- MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
- int count = 0;
+ int count = isEnum ? 2 : 0; // reserve 2 slots for special enum methods: #values() and #valueOf(String)
+ MethodBinding[] methodBindings = new MethodBinding[(clinitIndex == -1 ? size : size - 1) + count];
+ // create special methods for enums
+ if (isEnum) {
+ SourceTypeBinding sourceType = referenceContext.binding;
+ methodBindings[0] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUES); // add [] values()
+ methodBindings[1] = sourceType.addSyntheticEnumMethod(TypeConstants.VALUEOF); // add valueOf()
+ }
+ // create bindings for source methods
for (int i = 0; i < size; i++) {
if (i != clinitIndex) {
MethodScope scope = new MethodScope(this, methods[i], false);
@@ -242,7 +303,8 @@ public class ClassScope extends Scope {
referenceContext.binding.methods = methodBindings;
referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
}
- SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
+
+ SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
// provide the typeDeclaration with needed scopes
referenceContext.scope = this;
referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
@@ -259,49 +321,32 @@ public class ClassScope extends Scope {
}
SourceTypeBinding sourceType = referenceContext.binding;
+ environment().setAccessRestriction(sourceType, accessRestriction);
sourceType.fPackage.addType(sourceType);
checkAndSetModifiers();
+ buildTypeVariables();
+ buildMemberTypes(accessRestriction);
+ return sourceType;
+ }
+
+ private void buildTypeVariables() {
+
+ SourceTypeBinding sourceType = referenceContext.binding;
+ TypeParameter[] typeParameters = referenceContext.typeParameters;
+
+ // do not construct type variables if source < 1.5
+ if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
+ sourceType.typeVariables = NoTypeVariables;
+ return;
+ }
+ sourceType.typeVariables = NoTypeVariables; // safety
- // Look at member types
- ReferenceBinding[] memberTypeBindings = NoMemberTypes;
- if (referenceContext.memberTypes != null) {
- int size = referenceContext.memberTypes.length;
- memberTypeBindings = new ReferenceBinding[size];
- int count = 0;
- nextMember : for (int i = 0; i < size; i++) {
- TypeDeclaration memberContext = referenceContext.memberTypes[i];
- if (memberContext.isInterface()
- && sourceType.isNestedType()
- && sourceType.isClass()
- && !sourceType.isStatic()) {
- problemReporter().nestedClassCannotDeclareInterface(memberContext);
- continue nextMember;
- }
- ReferenceBinding type = sourceType;
- // check that the member does not conflict with an enclosing type
- do {
- if (CharOperation.equals(type.sourceName, memberContext.name)) {
- problemReporter().hidingEnclosingType(memberContext);
- continue nextMember;
- }
- type = type.enclosingType();
- } while (type != null);
- // check that the member type does not conflict with another sibling member type
- for (int j = 0; j < i; j++) {
- if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
- problemReporter().duplicateNestedType(memberContext);
- continue nextMember;
- }
- }
-
- ClassScope memberScope = new ClassScope(this, memberContext);
- memberTypeBindings[count++] = memberScope.buildType(sourceType, packageBinding);
- }
- if (count != size)
- System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
+ if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
+ problemReporter().objectCannotBeGeneric(referenceContext);
+ return;
}
- sourceType.memberTypes = memberTypeBindings;
- return sourceType;
+ sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
+ sourceType.modifiers |= AccGenericSignature;
}
private void checkAndSetModifiers() {
@@ -319,11 +364,18 @@ public class ClassScope extends Scope {
modifiers |= AccStrictfp;
if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
modifiers |= AccDeprecatedImplicitly;
- if (enclosingType.isInterface())
+ if ((enclosingType.modifiers & AccInterface) != 0)
modifiers |= AccPublic;
+ if (sourceType.isEnum())
+ modifiers |= AccStatic;
} else if (sourceType.isLocalType()) {
- if (sourceType.isAnonymousType())
+ if (sourceType.isAnonymousType()) {
modifiers |= AccFinal;
+ // set AccEnum flag for anonymous body of enum constants
+ if (referenceContext.allocation.type == null) {
+ modifiers |= AccEnum;
+ }
+ }
Scope scope = this;
do {
switch (scope.kind) {
@@ -368,13 +420,18 @@ public class ClassScope extends Scope {
// after this point, tests on the 16 bits reserved.
int realModifiers = modifiers & AccJustFlag;
- if ((realModifiers & AccInterface) != 0) {
+ if ((realModifiers & AccInterface) != 0) { // interface and annotation type
// detect abnormal cases for interfaces
if (isMemberType) {
int unexpectedModifiers =
- ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForMemberInterface(sourceType);
+ ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
+ if ((realModifiers & unexpectedModifiers) != 0) {
+ if ((realModifiers & AccAnnotation) != 0) {
+ problemReporter().illegalModifierForAnnotationMemberType(sourceType);
+ } else {
+ problemReporter().illegalModifierForMemberInterface(sourceType);
+ }
+ }
/*
} else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
@@ -382,13 +439,38 @@ public class ClassScope extends Scope {
problemReporter().illegalModifierForLocalInterface(sourceType);
*/
} else {
- int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
- if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForInterface(sourceType);
+ int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp | AccAnnotation);
+ if ((realModifiers & unexpectedModifiers) != 0) {
+ if ((realModifiers & AccAnnotation) != 0) {
+ problemReporter().illegalModifierForAnnotationType(sourceType);
+ } else {
+ problemReporter().illegalModifierForInterface(sourceType);
+ }
+ }
}
modifiers |= AccAbstract;
+ } else if ((realModifiers & AccEnum) != 0) {
+ // detect abnormal cases for enums
+ if (isMemberType) { // includes member types defined inside local types
+ int unexpectedModifiers =
+ ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccStrictfp | AccEnum);
+ if ((realModifiers & unexpectedModifiers) != 0)
+ problemReporter().illegalModifierForMemberEnum(sourceType);
+ } else if (sourceType.isLocalType()) {
+ int unexpectedModifiers = ~(AccStrictfp | AccFinal | AccEnum); // add final since implicitly set for anonymous type
+ if ((realModifiers & unexpectedModifiers) != 0)
+ problemReporter().illegalModifierForLocalEnum(sourceType);
+ } else {
+ int unexpectedModifiers = ~(AccPublic | AccStrictfp | AccEnum);
+ if ((realModifiers & unexpectedModifiers) != 0)
+ problemReporter().illegalModifierForEnum(sourceType);
+ }
+ if ((referenceContext.bits & ASTNode.HasAbstractMethods) != 0) {
+ modifiers |= AccAbstract;
+ }
+
} else {
- // detect abnormal cases for types
+ // detect abnormal cases for classes
if (isMemberType) { // includes member types defined inside local types
int unexpectedModifiers =
~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
@@ -417,9 +499,9 @@ public class ClassScope extends Scope {
// need to keep the less restrictive
if ((realModifiers & AccProtected) != 0)
- modifiers ^= AccProtected;
+ modifiers &= ~AccProtected;
if ((realModifiers & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
} else {
int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -429,13 +511,13 @@ public class ClassScope extends Scope {
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
+ modifiers &= ~AccProtected;
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
if ((accessorBits & AccProtected) != 0)
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
}
@@ -465,16 +547,30 @@ public class ClassScope extends Scope {
if ((modifiers & AccAlternateModifierProblem) != 0)
problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
- if (fieldBinding.declaringClass.isInterface()) {
+ if ((fieldBinding.declaringClass.modifiers & AccInterface) != 0) {
int expectedValue = AccPublic | AccStatic | AccFinal;
// set the modifiers
modifiers |= expectedValue;
// and then check that they are the only ones
- if ((modifiers & AccJustFlag) != expectedValue)
- problemReporter().illegalModifierForInterfaceField(fieldBinding.declaringClass, fieldDecl);
+ if ((modifiers & AccJustFlag) != expectedValue) {
+ if ((fieldBinding.declaringClass.modifiers & AccAnnotation) != 0) {
+ problemReporter().illegalModifierForAnnotationField(fieldDecl);
+ } else {
+ problemReporter().illegalModifierForInterfaceField(fieldDecl);
+ }
+ }
fieldBinding.modifiers = modifiers;
return;
+ } else if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ // check that they are not modifiers in source
+ if ((modifiers & AccJustFlag) != 0)
+ problemReporter().illegalModifierForEnumConstant(fieldBinding.declaringClass, fieldDecl);
+
+ // set the modifiers
+ int implicitValue = AccPublic | AccStatic | AccFinal | AccEnum;
+ fieldBinding.modifiers|= implicitValue;
+ return;
}
// after this point, tests on the 16 bits reserved.
@@ -493,13 +589,13 @@ public class ClassScope extends Scope {
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
+ modifiers &= ~AccProtected;
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
if ((accessorBits & AccProtected) != 0)
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
@@ -512,81 +608,85 @@ public class ClassScope extends Scope {
}
fieldBinding.modifiers = modifiers;
}
-
+
private void checkForInheritedMemberTypes(SourceTypeBinding sourceType) {
// search up the hierarchy of the sourceType to see if any superType defines a member type
// when no member types are defined, tag the sourceType & each superType with the HasNoMemberTypes bit
+ // assumes super types have already been checked & tagged
ReferenceBinding currentType = sourceType;
ReferenceBinding[][] interfacesToVisit = null;
int lastPosition = -1;
do {
- if ((currentType.tagBits & HasNoMemberTypes) != 0)
- break; // already know it has no inherited member types, can stop looking up
if (currentType.hasMemberTypes()) // avoid resolving member types eagerly
- return; // has member types
+ return;
+
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != NoSuperInterfaces) {
if (interfacesToVisit == null)
interfacesToVisit = new ReferenceBinding[5][];
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
- } while ((currentType = currentType.superclass()) != null);
+ } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
- boolean hasMembers = false;
if (interfacesToVisit != null) {
- done : for (int i = 0; i <= lastPosition; i++) {
+ // contains the interfaces between the sourceType and any superclass, which was tagged as having no member types
+ boolean needToTag = false;
+ for (int i = 0; i <= lastPosition; i++) {
ReferenceBinding[] interfaces = interfacesToVisit[i];
for (int j = 0, length = interfaces.length; j < length; j++) {
ReferenceBinding anInterface = interfaces[j];
- if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
- anInterface.tagBits |= InterfaceVisited;
- if ((anInterface.tagBits & HasNoMemberTypes) != 0)
- continue; // already know it has no inherited member types
- if (anInterface.memberTypes() != NoMemberTypes) {
- hasMembers = true;
- break done;
- }
+ if ((anInterface.tagBits & HasNoMemberTypes) == 0) { // skip interface if it already knows it has no member types
+ if (anInterface.hasMemberTypes()) // avoid resolving member types eagerly
+ return;
+ needToTag = true;
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != NoSuperInterfaces) {
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
}
}
}
- for (int i = 0; i <= lastPosition; i++) {
- ReferenceBinding[] interfaces = interfacesToVisit[i];
- for (int j = 0, length = interfaces.length; j < length; j++) {
- interfaces[j].tagBits &= ~InterfaceVisited;
- if (!hasMembers)
+ if (needToTag) {
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++)
interfaces[j].tagBits |= HasNoMemberTypes;
}
}
}
- if (!hasMembers) {
- currentType = sourceType;
- do {
- currentType.tagBits |= HasNoMemberTypes;
- } while ((currentType = currentType.superclass()) != null);
+ // tag the sourceType and all of its superclasses, unless they have already been tagged
+ currentType = sourceType;
+ do {
+ currentType.tagBits |= HasNoMemberTypes;
+ } while ((currentType = currentType.superclass()) != null && (currentType.tagBits & HasNoMemberTypes) == 0);
+ }
+ // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
+ private void checkParameterizedTypeBounds() {
+ TypeReference superclass = referenceContext.superclass;
+ if (superclass != null) {
+ superclass.checkBounds(this);
+ }
+ TypeReference[] superinterfaces = referenceContext.superInterfaces;
+ if (superinterfaces != null) {
+ for (int i = 0, length = superinterfaces.length; i < length; i++) {
+ superinterfaces[i].checkBounds(this);
+ }
+ }
+ TypeParameter[] typeParameters = referenceContext.typeParameters;
+ if (typeParameters != null) {
+ for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+ typeParameters[i].checkBounds(this);
+ }
}
}
-
+
private void connectMemberTypes() {
SourceTypeBinding sourceType = referenceContext.binding;
if (sourceType.memberTypes != NoMemberTypes)
@@ -606,26 +706,32 @@ public class ClassScope extends Scope {
*/
private boolean connectSuperclass() {
SourceTypeBinding sourceType = referenceContext.binding;
- if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
+ if (sourceType.id == T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
sourceType.superclass = null;
sourceType.superInterfaces = NoSuperInterfaces;
- if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
+ if (!sourceType.isClass())
+ problemReporter().objectMustBeClass(sourceType);
+ if (referenceContext.superclass != null || (referenceContext.superInterfaces != null && referenceContext.superInterfaces.length > 0))
problemReporter().objectCannotHaveSuperTypes(sourceType);
return true; // do not propagate Object's hierarchy problems down to every subtype
}
if (referenceContext.superclass == null) {
+ if (sourceType.isEnum() && environment().options.sourceLevel >= JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
+ return connectEnumSuperclass();
sourceType.superclass = getJavaLangObject();
- return !detectCycle(sourceType, sourceType.superclass, null);
- }
- ReferenceBinding superclass = findSupertype(referenceContext.superclass);
- if (superclass != null) { // is null if a cycle was detected cycle
- referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
- if (!superclass.isValidBinding()) {
- problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
- } else if (superclass.isInterface()) {
- problemReporter().superclassMustBeAClass(sourceType, referenceContext.superclass, superclass);
+ return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
+ }
+ TypeReference superclassRef = referenceContext.superclass;
+ ReferenceBinding superclass = findSupertype(superclassRef);
+ if (superclass != null) { // is null if a cycle was detected cycle or a problem
+ if (!superclass.isClass()) {
+ problemReporter().superclassMustBeAClass(sourceType, superclassRef, superclass);
} else if (superclass.isFinal()) {
- problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
+ problemReporter().classExtendFinalClass(sourceType, superclassRef, superclass);
+ } else if ((superclass.tagBits & TagBits.HasDirectWildcard) != 0) {
+ problemReporter().superTypeCannotUseWildcard(sourceType, superclassRef, superclass);
+ } else if (superclass.erasure().id == T_JavaLangEnum) {
+ problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
} else {
// only want to reach here when no errors are reported
sourceType.superclass = superclass;
@@ -635,10 +741,36 @@ public class ClassScope extends Scope {
sourceType.tagBits |= HierarchyHasProblems;
sourceType.superclass = getJavaLangObject();
if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
- detectCycle(sourceType, sourceType.superclass, null);
+ detectHierarchyCycle(sourceType, sourceType.superclass, null);
return false; // reported some error against the source type
}
+ /**
+ * enum X (implicitly) extends Enum
+ */
+ private boolean connectEnumSuperclass() {
+ SourceTypeBinding sourceType = referenceContext.binding;
+ ReferenceBinding rootEnumType = getJavaLangEnum();
+ boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
+ // arity check for well-known Enum
+ TypeVariableBinding[] refTypeVariables = rootEnumType.typeVariables();
+ if (refTypeVariables == NoTypeVariables) { // check generic
+ problemReporter().nonGenericTypeCannotBeParameterized(null, rootEnumType, new TypeBinding[]{ sourceType });
+ return false; // cannot reach here as AbortCompilation is thrown
+ } else if (1 != refTypeVariables.length) { // check arity
+ problemReporter().incorrectArityForParameterizedType(null, rootEnumType, new TypeBinding[]{ sourceType });
+ return false; // cannot reach here as AbortCompilation is thrown
+ }
+ // check argument type compatibility
+ ParameterizedTypeBinding superType = createParameterizedType(rootEnumType, new TypeBinding[]{ sourceType } , null);
+ sourceType.superclass = superType;
+ // bound check
+ if (!refTypeVariables[0].boundCheck(superType, sourceType)) {
+ problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
+ }
+ return !foundCycle;
+ }
+
/*
Our current belief based on available JCK 1.3 tests is:
inherited member types are visible as a potential superclass.
@@ -652,9 +784,16 @@ public class ClassScope extends Scope {
private boolean connectSuperInterfaces() {
SourceTypeBinding sourceType = referenceContext.binding;
sourceType.superInterfaces = NoSuperInterfaces;
- if (referenceContext.superInterfaces == null)
+ if (referenceContext.superInterfaces == null) {
+ if (sourceType.isAnnotationType() && environment().options.sourceLevel >= JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
+ ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
+ boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
+ sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
+ return !foundCycle;
+ }
return true;
- if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
+ }
+ if (sourceType.id == T_JavaLangObject) // already handled the case of redefining java.lang.Object
return true;
boolean noProblems = true;
@@ -662,21 +801,14 @@ public class ClassScope extends Scope {
ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
int count = 0;
nextInterface : for (int i = 0; i < length; i++) {
- ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
+ TypeReference superInterfaceRef = referenceContext.superInterfaces[i];
+ ReferenceBinding superInterface = findSupertype(superInterfaceRef);
if (superInterface == null) { // detected cycle
- noProblems = false;
- continue nextInterface;
- }
- referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
- if (!superInterface.isValidBinding()) {
- problemReporter().invalidSuperinterface(
- sourceType,
- referenceContext.superInterfaces[i],
- superInterface);
sourceType.tagBits |= HierarchyHasProblems;
noProblems = false;
continue nextInterface;
}
+ superInterfaceRef.resolvedType = superInterface; // hold onto the problem type
// Check for a duplicate interface once the name is resolved, otherwise we may be confused (ie : a.b.I and c.d.I)
for (int k = 0; k < count; k++) {
if (interfaceBindings[k] == superInterface) {
@@ -685,8 +817,26 @@ public class ClassScope extends Scope {
continue nextInterface;
}
}
- if (superInterface.isClass()) {
- problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
+ if (!superInterface.isInterface()) {
+ problemReporter().superinterfaceMustBeAnInterface(sourceType, superInterfaceRef, superInterface);
+ sourceType.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextInterface;
+ }
+ if ((superInterface.tagBits & TagBits.HasDirectWildcard) != 0) {
+ problemReporter().superTypeCannotUseWildcard(sourceType, superInterfaceRef, superInterface);
+ sourceType.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextInterface;
+ }
+ ReferenceBinding invalid = findAmbiguousInterface(superInterface, sourceType);
+ if (invalid != null) {
+ ReferenceBinding generic = null;
+ if (superInterface.isParameterizedType())
+ generic = ((ParameterizedTypeBinding) superInterface).type;
+ else if (invalid.isParameterizedType())
+ generic = ((ParameterizedTypeBinding) invalid).type;
+ problemReporter().superinterfacesCollide(generic, referenceContext, superInterface, invalid);
sourceType.tagBits |= HierarchyHasProblems;
noProblems = false;
continue nextInterface;
@@ -707,15 +857,16 @@ public class ClassScope extends Scope {
void connectTypeHierarchy() {
SourceTypeBinding sourceType = referenceContext.binding;
if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
- boolean noProblems = true;
sourceType.tagBits |= BeginHierarchyCheck;
- if (sourceType.isClass())
- noProblems &= connectSuperclass();
+ boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
+ noProblems &= connectSuperclass();
noProblems &= connectSuperInterfaces();
sourceType.tagBits |= EndHierarchyCheck;
if (noProblems && sourceType.isHierarchyInconsistent())
problemReporter().hierarchyHasProblems(sourceType);
}
+ // Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
+ checkParameterizedTypeBounds();
connectMemberTypes();
try {
checkForInheritedMemberTypes(sourceType);
@@ -740,27 +891,80 @@ public class ClassScope extends Scope {
if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
return;
- boolean noProblems = true;
sourceType.tagBits |= BeginHierarchyCheck;
- if (sourceType.isClass())
- noProblems &= connectSuperclass();
+ boolean noProblems = connectTypeVariables(referenceContext.typeParameters);
+ noProblems &= connectSuperclass();
noProblems &= connectSuperInterfaces();
sourceType.tagBits |= EndHierarchyCheck;
if (noProblems && sourceType.isHierarchyInconsistent())
problemReporter().hierarchyHasProblems(sourceType);
}
-
+
+ public boolean detectAnnotationCycle(TypeBinding sourceType, TypeBinding annotationElementType, TypeReference reference) {
+ if (!annotationElementType.isAnnotationType())
+ return false;
+
+ if (sourceType == annotationElementType) {
+ problemReporter().annotationCircularity(sourceType, annotationElementType, reference);
+ return true;
+ }
+ // TODO (kent) add support for detecting indirect cases using TagBits.BeginAnnotationCheck/EndAnnotationCheck
+ return false;
+ }
+
+ public boolean detectHierarchyCycle(TypeBinding superType, TypeReference reference, TypeBinding[] argTypes) {
+ if (!(superType instanceof ReferenceBinding)) return false;
+
+ if (argTypes != null) {
+ for (int i = 0, l = argTypes.length; i < l; i++) {
+ TypeBinding argType = argTypes[i].leafComponentType();
+ if ((argType.tagBits & BeginHierarchyCheck) == 0 && argType instanceof SourceTypeBinding)
+ // ensure if this is a source argument type that it has already been checked
+ ((SourceTypeBinding) argType).scope.connectTypeHierarchyWithoutMembers();
+ }
+ }
+
+ if (reference == this.superTypeReference) { // see findSuperType()
+ if (superType.isTypeVariable())
+ return false; // error case caught in resolveSuperType()
+ // abstract class X implements java.util.Map
+ // static abstract class M implements Entry
+ if (superType.isParameterizedType())
+ superType = ((ParameterizedTypeBinding) superType).type;
+ compilationUnitScope().recordSuperTypeReference(superType); // to record supertypes
+ return detectHierarchyCycle(referenceContext.binding, (ReferenceBinding) superType, reference);
+ }
+
+ if ((superType.tagBits & BeginHierarchyCheck) == 0 && superType instanceof SourceTypeBinding)
+ // ensure if this is a source superclass that it has already been checked
+ ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
+ return false;
+ }
+
// Answer whether a cycle was found between the sourceType & the superType
- private boolean detectCycle(
- SourceTypeBinding sourceType,
- ReferenceBinding superType,
- TypeReference reference) {
+ private boolean detectHierarchyCycle(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
+ if (superType.isRawType())
+ superType = ((RawTypeBinding) superType).type;
+ // by this point the superType must be a binary or source type
+
if (sourceType == superType) {
problemReporter().hierarchyCircularity(sourceType, superType, reference);
sourceType.tagBits |= HierarchyHasProblems;
return true;
}
+ if (superType.isMemberType()) {
+ ReferenceBinding current = superType.enclosingType();
+ do {
+ if (current.isHierarchyBeingConnected()) {
+ problemReporter().hierarchyCircularity(sourceType, current, reference);
+ sourceType.tagBits |= HierarchyHasProblems;
+ current.tagBits |= HierarchyHasProblems;
+ return true;
+ }
+ } while ((current = current.enclosingType()) != null);
+ }
+
if (superType.isBinaryBinding()) {
// force its superclass & superinterfaces to be found... 2 possibilities exist - the source type is included in the hierarchy of:
// - a binary type... this case MUST be caught & reported here
@@ -773,10 +977,13 @@ public class ClassScope extends Scope {
superType.tagBits |= HierarchyHasProblems;
return true;
}
- hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
- if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
+ ReferenceBinding parentType = superType.superclass();
+ if (parentType.isParameterizedType())
+ parentType = ((ParameterizedTypeBinding) parentType).type;
+ hasCycle |= detectHierarchyCycle(sourceType, parentType, reference);
+ if ((parentType.tagBits & HierarchyHasProblems) != 0) {
sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
+ parentType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
}
}
@@ -790,7 +997,9 @@ public class ClassScope extends Scope {
superType.tagBits |= HierarchyHasProblems;
return true;
}
- hasCycle |= detectCycle(sourceType, anInterface, reference);
+ if (anInterface.isParameterizedType())
+ anInterface = ((ParameterizedTypeBinding) anInterface).type;
+ hasCycle |= detectHierarchyCycle(sourceType, anInterface, reference);
if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
sourceType.tagBits |= HierarchyHasProblems;
superType.tagBits |= HierarchyHasProblems;
@@ -800,93 +1009,68 @@ public class ClassScope extends Scope {
return hasCycle;
}
- if ((superType.tagBits & EndHierarchyCheck) == 0
- && (superType.tagBits & BeginHierarchyCheck) != 0) {
- problemReporter().hierarchyCircularity(sourceType, superType, reference);
- sourceType.tagBits |= HierarchyHasProblems;
- superType.tagBits |= HierarchyHasProblems;
- return true;
+ if (superType.isHierarchyBeingConnected()) {
+ if (((SourceTypeBinding) superType).scope.superTypeReference != null) { // if null then its connecting its type variables
+ problemReporter().hierarchyCircularity(sourceType, superType, reference);
+ sourceType.tagBits |= HierarchyHasProblems;
+ superType.tagBits |= HierarchyHasProblems;
+ return true;
+ }
}
if ((superType.tagBits & BeginHierarchyCheck) == 0)
// ensure if this is a source superclass that it has already been checked
- ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
+ ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers();
if ((superType.tagBits & HierarchyHasProblems) != 0)
sourceType.tagBits |= HierarchyHasProblems;
return false;
}
-
- private ReferenceBinding findSupertype(TypeReference typeReference) {
- try {
- typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
- char[][] compoundName = typeReference.getTypeName();
- compilationUnitScope().recordQualifiedReference(compoundName);
- SourceTypeBinding sourceType = referenceContext.binding;
- int size = compoundName.length;
- int n = 1;
- ReferenceBinding superType;
-
- // resolve the first name of the compoundName
- if (CharOperation.equals(compoundName[0], sourceType.sourceName)) {
- superType = sourceType;
- // match against the sourceType even though nested members cannot be supertypes
- } else {
- Binding typeOrPackage = parent.getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
- if (typeOrPackage == null || !typeOrPackage.isValidBinding())
- return new ProblemReferenceBinding(
- compoundName[0],
- typeOrPackage == null ? NotFound : typeOrPackage.problemId());
-
- boolean checkVisibility = false;
- for (; n < size; n++) {
- if (!(typeOrPackage instanceof PackageBinding))
- break;
- PackageBinding packageBinding = (PackageBinding) typeOrPackage;
- typeOrPackage = packageBinding.getTypeOrPackage(compoundName[n]);
- if (typeOrPackage == null || !typeOrPackage.isValidBinding())
- return new ProblemReferenceBinding(
- CharOperation.subarray(compoundName, 0, n + 1),
- typeOrPackage == null ? NotFound : typeOrPackage.problemId());
- checkVisibility = true;
- }
-
- // convert to a ReferenceBinding
- if (typeOrPackage instanceof PackageBinding) // error, the compoundName is a packageName
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
- superType = (ReferenceBinding) typeOrPackage;
- compilationUnitScope().recordTypeReference(superType); // to record supertypes
-
- if (checkVisibility
- && n == size) { // if we're finished and know the final supertype then check visibility
- if (!superType.canBeSeenBy(sourceType.fPackage))
- // its a toplevel type so just check package access
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), superType, NotVisible);
- }
+
+ private ReferenceBinding findAmbiguousInterface(ReferenceBinding newInterface, ReferenceBinding currentType) {
+ TypeBinding newErasure = newInterface.erasure();
+ if (newInterface == newErasure) return null;
+
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
}
- // at this point we know we have a type but we have to look for cycles
- while (true) {
- // must detect cycles & force connection up the hierarchy... also handle cycles with binary types.
- // must be guaranteed that the superType knows its entire hierarchy
- if (detectCycle(sourceType, superType, typeReference))
- return null; // cycle error was already reported
-
- if (n >= size)
- break;
-
- // retrieve the next member type
- char[] typeName = compoundName[n++];
- superType = findMemberType(typeName, superType);
- if (superType == null)
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, n), NotFound);
- if (!superType.isValidBinding()) {
- superType.compoundName = CharOperation.subarray(compoundName, 0, n);
- return superType;
+ } while ((currentType = currentType.superclass()) != null);
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ currentType = interfaces[j];
+ if (currentType.erasure() == newErasure)
+ if (currentType != newInterface)
+ return currentType;
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
}
}
+ }
+ return null;
+ }
+
+ private ReferenceBinding findSupertype(TypeReference typeReference) {
+ try {
+ typeReference.aboutToResolve(this); // allows us to trap completion & selection nodes
+ compilationUnitScope().recordQualifiedReference(typeReference.getTypeName());
+ this.superTypeReference = typeReference;
+ ReferenceBinding superType = (ReferenceBinding) typeReference.resolveSuperType(this);
+ this.superTypeReference = null;
return superType;
} catch (AbortCompilation e) {
e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
throw e;
- }
+ }
}
/* Answer the problem reporter to use for raising new problems.
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/src/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index d4a8d4f..9033073 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -11,16 +11,11 @@
package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.compiler.util.CompoundNameVector;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.compiler.util.SimpleNameVector;
+import org.eclipse.jdt.internal.compiler.util.*;
public class CompilationUnitScope extends Scope {
@@ -36,6 +31,7 @@ public class CompilationUnitScope extends Scope {
private CompoundNameVector qualifiedReferences;
private SimpleNameVector simpleNameReferences;
private ObjectVector referencedTypes;
+ private ObjectVector referencedSuperTypes;
HashtableOfType constantPoolNameUsage;
@@ -50,17 +46,19 @@ public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment e
this.qualifiedReferences = new CompoundNameVector();
this.simpleNameReferences = new SimpleNameVector();
this.referencedTypes = new ObjectVector();
+ this.referencedSuperTypes = new ObjectVector();
} else {
this.qualifiedReferences = null; // used to test if dependencies should be recorded
this.simpleNameReferences = null;
this.referencedTypes = null;
+ this.referencedSuperTypes = null;
}
}
void buildFieldsAndMethods() {
for (int i = 0, length = topLevelTypes.length; i < length; i++)
topLevelTypes[i].scope.buildFieldsAndMethods();
}
-void buildTypeBindings() {
+void buildTypeBindings(AccessRestriction accessRestriction) {
topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
if (referenceContext.compilationResult.compilationUnit != null) {
char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
@@ -120,7 +118,7 @@ void buildTypeBindings() {
}
ClassScope child = new ClassScope(this, typeDecl);
- SourceTypeBinding type = child.buildType(null, fPackage);
+ SourceTypeBinding type = child.buildType(null, fPackage, accessRestriction);
if(type != null) {
topLevelTypes[count++] = type;
}
@@ -141,7 +139,7 @@ void checkAndSetImports() {
int numberOfImports = numberOfStatements + 1;
for (int i = 0; i < numberOfStatements; i++) {
ImportReference importReference = referenceContext.imports[i];
- if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+ if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
numberOfImports--;
break;
}
@@ -155,20 +153,23 @@ void checkAndSetImports() {
char[][] compoundName = importReference.tokens;
// skip duplicates or imports of the current package
- for (int j = 0; j < index; j++)
- if (resolvedImports[j].onDemand == importReference.onDemand)
+ for (int j = 0; j < index; j++) {
+ ImportBinding resolved = resolvedImports[j];
+ if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic())
if (CharOperation.equals(compoundName, resolvedImports[j].compoundName))
continue nextImport;
- if (importReference.onDemand == true)
+ }
+
+ if (importReference.onDemand) {
if (CharOperation.equals(compoundName, currentPackageName))
continue nextImport;
- if (importReference.onDemand) {
- Binding importBinding = findOnDemandImport(compoundName);
- if (!importBinding.isValidBinding())
+ Binding importBinding = findImport(compoundName, compoundName.length);
+ if (!importBinding.isValidBinding() || (importReference.isStatic() && importBinding instanceof PackageBinding))
continue nextImport; // we report all problems in faultInImports()
resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
} else {
+ // resolve single imports only when the last name matches
resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
}
}
@@ -261,7 +262,7 @@ void faultInImports() {
int numberOfImports = numberOfStatements + 1;
for (int i = 0; i < numberOfStatements; i++) {
ImportReference importReference = referenceContext.imports[i];
- if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+ if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
numberOfImports--;
break;
}
@@ -270,63 +271,73 @@ void faultInImports() {
resolvedImports[0] = getDefaultImports()[0];
int index = 1;
+ // keep static imports with normal imports until there is a reason to split them up
+ // on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
+ // single imports change from being just types to types or fields
nextImport : for (int i = 0; i < numberOfStatements; i++) {
ImportReference importReference = referenceContext.imports[i];
char[][] compoundName = importReference.tokens;
// skip duplicates or imports of the current package
- for (int j = 0; j < index; j++)
- if (resolvedImports[j].onDemand == importReference.onDemand)
- if (CharOperation.equals(compoundName, resolvedImports[j].compoundName)) {
+ for (int j = 0; j < index; j++) {
+ ImportBinding resolved = resolvedImports[j];
+ if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic()) {
+ if (CharOperation.equals(compoundName, resolved.compoundName)) {
problemReporter().unusedImport(importReference); // since skipped, must be reported now
continue nextImport;
}
- if (importReference.onDemand == true)
+ }
+ }
+ if (importReference.onDemand) {
if (CharOperation.equals(compoundName, currentPackageName)) {
problemReporter().unusedImport(importReference); // since skipped, must be reported now
continue nextImport;
}
- if (importReference.onDemand) {
- Binding importBinding = findOnDemandImport(compoundName);
+
+ Binding importBinding = findImport(compoundName, compoundName.length);
if (!importBinding.isValidBinding()) {
problemReporter().importProblem(importReference, importBinding);
continue nextImport;
}
+ if (importReference.isStatic() && importBinding instanceof PackageBinding) {
+ problemReporter().cannotImportPackage(importReference);
+ continue nextImport;
+ }
resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
} else {
- Binding typeBinding = findSingleTypeImport(compoundName);
- if (!typeBinding.isValidBinding()) {
- problemReporter().importProblem(importReference, typeBinding);
+ Binding importBinding = findSingleImport(compoundName, importReference.isStatic());
+ if (!importBinding.isValidBinding()) {
+ problemReporter().importProblem(importReference, importBinding);
continue nextImport;
}
- if (typeBinding instanceof PackageBinding) {
+ if (importBinding instanceof PackageBinding) {
problemReporter().cannotImportPackage(importReference);
continue nextImport;
}
- if (typeBinding instanceof ReferenceBinding) {
- ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
- if (importReference.isTypeUseDeprecated(referenceBinding, this)) {
- problemReporter().deprecatedType((TypeBinding) typeBinding, importReference);
- }
- }
- ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
- if (existingType != null) {
- // duplicate test above should have caught this case, but make sure
- if (existingType == typeBinding) {
- continue nextImport;
- }
- // either the type collides with a top level type or another imported type
- for (int j = 0, length = topLevelTypes.length; j < length; j++) {
- if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
- problemReporter().conflictingImport(importReference);
+ // collisions between an imported static field & a type should be checked according to spec... but currently not by javac
+ if (importBinding instanceof ReferenceBinding) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) importBinding;
+ if (importReference.isTypeUseDeprecated(referenceBinding, this))
+ problemReporter().deprecatedType(referenceBinding, importReference);
+
+ ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
+ if (existingType != null) {
+ // duplicate test above should have caught this case, but make sure
+ if (existingType == referenceBinding)
continue nextImport;
+ // either the type collides with a top level type or another imported type
+ for (int j = 0, length = topLevelTypes.length; j < length; j++) {
+ if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
+ problemReporter().conflictingImport(importReference);
+ continue nextImport;
+ }
}
+ problemReporter().duplicateImport(importReference);
+ continue nextImport;
}
- problemReporter().duplicateImport(importReference);
- continue nextImport;
+ typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
}
- resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
- typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
+ resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference);
}
}
@@ -339,7 +350,7 @@ void faultInImports() {
resolvedSingeTypeImports = new HashtableOfObject(length);
for (int i = 0; i < length; i++) {
ImportBinding binding = imports[i];
- if (!binding.onDemand)
+ if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding)
resolvedSingeTypeImports.put(binding.compoundName[binding.compoundName.length - 1], binding);
}
}
@@ -349,12 +360,11 @@ public void faultInTypes() {
for (int i = 0, length = topLevelTypes.length; i < length; i++)
topLevelTypes[i].faultInTypesForFieldsAndMethods();
}
-private Binding findOnDemandImport(char[][] compoundName) {
+private Binding findImport(char[][] compoundName, int length) {
recordQualifiedReference(compoundName);
Binding binding = environment.getTopLevelPackage(compoundName[0]);
int i = 1;
- int length = compoundName.length;
foundNothingOrType: if (binding != null) {
PackageBinding packageBinding = (PackageBinding) binding;
while (i < length) {
@@ -373,50 +383,70 @@ private Binding findOnDemandImport(char[][] compoundName) {
ReferenceBinding type;
if (binding == null) {
- if (environment.defaultPackage == null
- || environment.options.complianceLevel >= ClassFileConstants.JDK1_4){
- return new ProblemReferenceBinding(
- CharOperation.subarray(compoundName, 0, i),
- NotFound);
- }
+ if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+ return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
type = findType(compoundName[0], environment.defaultPackage, environment.defaultPackage);
if (type == null || !type.isValidBinding())
- return new ProblemReferenceBinding(
- CharOperation.subarray(compoundName, 0, i),
- NotFound);
+ return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
i = 1; // reset to look for member types inside the default package type
} else {
type = (ReferenceBinding) binding;
}
- for (; i < length; i++) {
- if (!type.canBeSeenBy(fPackage)) {
- return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);
- }
- // does not look for inherited member types on purpose
- if ((type = type.getMemberType(compoundName[i])) == null) {
- return new ProblemReferenceBinding(
- CharOperation.subarray(compoundName, 0, i + 1),
- NotFound);
- }
+ while (i < length) {
+ if (!type.canBeSeenBy(fPackage))
+ return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);
+
+ char[] name = compoundName[i++];
+ // does not look for inherited member types on purpose, only immediate members
+ type = type.getMemberType(name);
+ if (type == null)
+ return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
}
if (!type.canBeSeenBy(fPackage))
return new ProblemReferenceBinding(compoundName, type, NotVisible);
return type;
}
-private Binding findSingleTypeImport(char[][] compoundName) {
+private Binding findSingleImport(char[][] compoundName, boolean findStaticImports) {
if (compoundName.length == 1) {
// findType records the reference
// the name cannot be a package
- if (environment.defaultPackage == null
- || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+ if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
return new ProblemReferenceBinding(compoundName, NotFound);
ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
if (typeBinding == null)
return new ProblemReferenceBinding(compoundName, NotFound);
return typeBinding;
}
- return findOnDemandImport(compoundName);
+
+ if (findStaticImports)
+ return findSingleStaticImport(compoundName);
+ return findImport(compoundName, compoundName.length);
+}
+private Binding findSingleStaticImport(char[][] compoundName) {
+ Binding binding = findImport(compoundName, compoundName.length - 1);
+ if (!binding.isValidBinding()) return binding;
+
+ char[] name = compoundName[compoundName.length - 1];
+ if (binding instanceof PackageBinding) {
+ Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
+ if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type
+ return new ProblemReferenceBinding(compoundName, InvalidTypeForStaticImport);
+ return binding; // cannot be a package, error is caught in sender
+ }
+
+ // look to see if its a static field first
+ ReferenceBinding type = (ReferenceBinding) binding;
+ FieldBinding field = findField(type, name, null, true);
+ if (field != null && field.isStatic() && field.canBeSeenBy(fPackage))
+ return field;
+
+ type = findMemberType(name, type);
+ if (type == null || !type.isStatic())
+ return new ProblemReferenceBinding(compoundName, type, NotFound);
+ if (!type.canBeSeenBy(fPackage))
+ return new ProblemReferenceBinding(compoundName, type, NotVisible);
+ return type;
}
ImportBinding[] getDefaultImports() {
// initialize the default imports if necessary... share the default java.lang.* import
@@ -432,6 +462,12 @@ ImportBinding[] getDefaultImports() {
return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
}
+// NOT Public API
+public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
+ if (onDemand)
+ return findImport(compoundName, compoundName.length);
+ return findSingleImport(compoundName, isStaticImport);
+}
/* Answer the problem reporter to use for raising new problems.
*
* Note that as a side-effect, this updates the current reference context
@@ -505,53 +541,55 @@ void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
recordQualifiedReference(qualifiedEnclosingName);
recordSimpleReference(simpleName);
}
+void recordReference(ReferenceBinding type, char[] simpleName) {
+ ReferenceBinding actualType = typeToRecord(type);
+ if (actualType != null)
+ recordReference(actualType.compoundName, simpleName);
+}
void recordSimpleReference(char[] simpleName) {
if (simpleNameReferences == null) return; // not recording dependencies
if (!simpleNameReferences.contains(simpleName))
simpleNameReferences.add(simpleName);
}
+void recordSuperTypeReference(TypeBinding type) {
+ if (referencedSuperTypes == null) return; // not recording dependencies
+
+ ReferenceBinding actualType = typeToRecord(type);
+ if (actualType != null && !referencedSuperTypes.containsIdentical(actualType))
+ referencedSuperTypes.add(actualType);
+}
+public void recordTypeConversion(TypeBinding superType, TypeBinding subType) {
+ recordSuperTypeReference(subType); // must record the hierarchy of the subType that is converted to the superType
+}
void recordTypeReference(TypeBinding type) {
if (referencedTypes == null) return; // not recording dependencies
- if (type.isArrayType())
- type = ((ArrayBinding) type).leafComponentType;
-
- if (type.isBaseType()) return;
- if (referencedTypes.containsIdentical(type)) return;
- if (((ReferenceBinding) type).isLocalType()) return;
-
- referencedTypes.add(type);
+ ReferenceBinding actualType = typeToRecord(type);
+ if (actualType != null && !referencedTypes.containsIdentical(actualType))
+ referencedTypes.add(actualType);
}
void recordTypeReferences(TypeBinding[] types) {
- if (qualifiedReferences == null) return; // not recording dependencies
+ if (referencedTypes == null) return; // not recording dependencies
if (types == null || types.length == 0) return;
for (int i = 0, max = types.length; i < max; i++) {
// No need to record supertypes of method arguments & thrown exceptions, just the compoundName
// If a field/method is retrieved from such a type then a separate call does the job
- TypeBinding type = types[i];
- if (type.isArrayType())
- type = ((ArrayBinding) type).leafComponentType;
- if (!type.isBaseType()) {
- ReferenceBinding actualType = (ReferenceBinding) type;
- if (!actualType.isLocalType())
- recordQualifiedReference(actualType.isMemberType()
- ? CharOperation.splitOn('.', actualType.readableName())
- : actualType.compoundName);
- }
+ ReferenceBinding actualType = typeToRecord(types[i]);
+ if (actualType != null && !referencedTypes.containsIdentical(actualType))
+ referencedTypes.add(actualType);
}
}
-Binding resolveSingleTypeImport(ImportBinding importBinding) {
+Binding resolveSingleImport(ImportBinding importBinding) {
if (importBinding.resolvedImport == null) {
- importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
+ importBinding.resolvedImport = findSingleImport(importBinding.compoundName, importBinding.isStatic());
if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
- if (this.imports != null){
+ if (this.imports != null) {
ImportBinding[] newImports = new ImportBinding[imports.length - 1];
for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
- if (this.imports[i] != importBinding){
+ if (this.imports[i] != importBinding)
newImports[n++] = this.imports[i];
- }
this.imports = newImports;
}
return null;
@@ -560,26 +598,33 @@ Binding resolveSingleTypeImport(ImportBinding importBinding) {
return importBinding.resolvedImport;
}
public void storeDependencyInfo() {
- // add the type hierarchy of each referenced type
+ // add the type hierarchy of each referenced supertype
// cannot do early since the hierarchy may not be fully resolved
- for (int i = 0; i < referencedTypes.size; i++) { // grows as more types are added
- ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+ for (int i = 0; i < referencedSuperTypes.size; i++) { // grows as more types are added
+ ReferenceBinding type = (ReferenceBinding) referencedSuperTypes.elementAt(i);
+ if (!referencedTypes.containsIdentical(type))
+ referencedTypes.add(type);
+
if (!type.isLocalType()) {
- recordQualifiedReference(type.isMemberType()
- ? CharOperation.splitOn('.', type.readableName())
- : type.compoundName);
ReferenceBinding enclosing = type.enclosingType();
- if (enclosing != null && !referencedTypes.containsIdentical(enclosing))
- referencedTypes.add(enclosing); // to record its supertypes
+ if (enclosing != null)
+ recordSuperTypeReference(enclosing);
}
ReferenceBinding superclass = type.superclass();
- if (superclass != null && !referencedTypes.containsIdentical(superclass))
- referencedTypes.add(superclass); // to record its supertypes
+ if (superclass != null)
+ recordSuperTypeReference(superclass);
ReferenceBinding[] interfaces = type.superInterfaces();
- if (interfaces != null && interfaces.length > 0)
+ if (interfaces != null)
for (int j = 0, length = interfaces.length; j < length; j++)
- if (!referencedTypes.containsIdentical(interfaces[j]))
- referencedTypes.add(interfaces[j]); // to record its supertypes
+ recordSuperTypeReference(interfaces[j]);
+ }
+
+ for (int i = 0, l = referencedTypes.size; i < l; i++) {
+ ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+ if (!type.isLocalType())
+ recordQualifiedReference(type.isMemberType()
+ ? CharOperation.splitOn('.', type.readableName())
+ : type.compoundName);
}
int size = qualifiedReferences.size;
@@ -597,6 +642,25 @@ public void storeDependencyInfo() {
public String toString() {
return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
}
+private ReferenceBinding typeToRecord(TypeBinding type) {
+ if (type.isArrayType())
+ type = ((ArrayBinding) type).leafComponentType;
+
+ switch (type.kind()) {
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ return null;
+ case Binding.PARAMETERIZED_TYPE :
+ case Binding.RAW_TYPE :
+ type = type.erasure();
+ }
+
+ if (type instanceof ReferenceBinding) {
+ ReferenceBinding refType = (ReferenceBinding) type;
+ if (!refType.isLocalType()) return refType;
+ }
+ return null;
+}
public void verifyMethods(MethodVerifier verifier) {
for (int i = 0, length = topLevelTypes.length; i < length; i++)
topLevelTypes[i].verifyMethods(verifier);
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java b/src/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
index 31f21cc..f8e80f1 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
@@ -10,30 +10,34 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
public interface CompilerModifiers extends ClassFileConstants { // modifier constant
// those constants are depending upon ClassFileConstants (relying that classfiles only use the 16 lower bits)
final int AccDefault = 0;
- final int AccJustFlag = 0xFFFF;
- final int AccCatchesExceptions = 0x10000; // bit17
- final int AccThrowsExceptions = 0x20000; // bit18 - also IConstants.AccSynthetic
- final int AccProblem = 0x40000; // bit19
- final int AccFromClassFile = 0x80000; // bit20
- final int AccIsConstantValue = 0x80000; // bit20
- final int AccDefaultAbstract = 0x80000; // bit20
+ final int AccJustFlag = // 16 lower bits
+ ASTNode.Bit1|ASTNode.Bit2|ASTNode.Bit3|ASTNode.Bit4|ASTNode.Bit5|ASTNode.Bit6|ASTNode.Bit7|ASTNode.Bit8|
+ ASTNode.Bit9|ASTNode.Bit10|ASTNode.Bit11|ASTNode.Bit12|ASTNode.Bit13|ASTNode.Bit14|ASTNode.Bit15|ASTNode.Bit16;
+
+ // bit17 - free
+ // bit18 - IConstants.AccAnnotationDefault
+ final int AccRestrictedAccess = ASTNode.Bit19;
+ final int AccFromClassFile = ASTNode.Bit20;
+ final int AccDefaultAbstract = ASTNode.Bit20;
// bit21 - IConstants.AccDeprecated
- final int AccDeprecatedImplicitly = 0x200000; // bit22 to record whether deprecated itself or contained by a deprecated type
- final int AccAlternateModifierProblem = 0x400000; // bit23
- final int AccModifierProblem = 0x800000; // bit24
- final int AccSemicolonBody = 0x1000000; // bit25
- final int AccUnresolved = 0x2000000; // bit26
- final int AccClearPrivateModifier = 0x4000000; // bit27 might be requested during private access emulation
- final int AccBlankFinal = 0x4000000; // bit27 for blank final variables
- final int AccIsDefaultConstructor = 0x4000000; // bit27 for default constructor
- final int AccPrivateUsed = 0x8000000; // bit28 used to diagnose unused private members
+ final int AccDeprecatedImplicitly = ASTNode.Bit22; // record whether deprecated itself or contained by a deprecated type
+ final int AccAlternateModifierProblem = ASTNode.Bit23;
+ final int AccModifierProblem = ASTNode.Bit24;
+ final int AccSemicolonBody = ASTNode.Bit25;
+ final int AccUnresolved = ASTNode.Bit26;
+ final int AccClearPrivateModifier = ASTNode.Bit27; // might be requested during private access emulation
+ final int AccBlankFinal = ASTNode.Bit27; // for blank final variables
+ final int AccIsDefaultConstructor = ASTNode.Bit27; // for default constructor
+ final int AccPrivateUsed = ASTNode.Bit28; // used to diagnose unused private members
final int AccVisibilityMASK = AccPublic | AccProtected | AccPrivate;
- final int AccOverriding = 0x10000000; // bit29 to record fact a method overrides another one
- final int AccImplementing = 0x20000000; // bit30 to record fact a method implements another one (it is concrete and overrides an abstract one)
+ final int AccOverriding = ASTNode.Bit29; // record fact a method overrides another one
+ final int AccImplementing = ASTNode.Bit30; // record fact a method implements another one (it is concrete and overrides an abstract one)
+ final int AccGenericSignature = ASTNode.Bit31; // record fact a type/method/field involves generics in its signature (and need special signature attr)
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 4889096..f84a723 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -10,20 +10,19 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.impl.Constant;
public class FieldBinding extends VariableBinding {
public ReferenceBinding declaringClass;
protected FieldBinding() {
+ super(null, null, 0, null);
// for creating problem field
}
public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
- this.modifiers = modifiers;
- this.type = type;
- this.name = name;
+ super(name, type, modifiers, constant);
this.declaringClass = declaringClass;
- this.constant = constant;
// propagate the deprecated modifier
if (this.declaringClass != null)
@@ -36,20 +35,27 @@ public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, Ref
}
// special API used to change field declaring class for runtime visibility check
public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
- this.modifiers = initialFieldBinding.modifiers;
- this.type = initialFieldBinding.type;
- this.name = initialFieldBinding.name;
+ super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
this.declaringClass = declaringClass;
- this.constant = initialFieldBinding.constant;
this.id = initialFieldBinding.id;
}
/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
+public final int kind() {
return FIELD;
}
+/* Answer true if the receiver is visible to the invocationPackage.
+*/
+
+public final boolean canBeSeenBy(PackageBinding invocationPackage) {
+ if (isPublic()) return true;
+ if (isPrivate()) return false;
+
+ // isProtected() or isDefault()
+ return invocationPackage == declaringClass.getPackage();
+}
/* Answer true if the receiver is visible to the type provided by the scope.
* InvocationSite implements isSuperAccess() to provide additional information
* if the receiver is protected.
@@ -101,7 +107,15 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
if (isPrivate()) {
// answer true if the receiverType is the declaringClass
// AND the invocationType and the declaringClass have a common enclosingType
- if (receiverType != declaringClass) return false;
+ receiverCheck: {
+ if (receiverType != declaringClass) {
+ // special tolerance for type variable direct bounds
+ if (receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(declaringClass.erasure())) {
+ break receiverCheck;
+ }
+ return false;
+ }
+ }
if (invocationType != declaringClass) {
ReferenceBinding outerInvocationType = invocationType;
@@ -111,7 +125,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
temp = temp.enclosingType();
}
- ReferenceBinding outerDeclaringClass = declaringClass;
+ ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
temp = outerDeclaringClass.enclosingType();
while (temp != null) {
outerDeclaringClass = temp;
@@ -136,6 +150,28 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
} while ((currentType = currentType.superclass()) != null);
return false;
}
+/*
+ * declaringUniqueKey dot fieldName
+ * p.X { X x} --> Lp/X;.x;
+ */
+public char[] computeUniqueKey() {
+ char[] declaringKey = this.declaringClass == null /*case of length field for an array*/ ? CharOperation.NO_CHAR : this.declaringClass.computeUniqueKey();
+ int declaringLength = declaringKey.length;
+ int nameLength = this.name.length;
+ char[] uniqueKey = new char[declaringLength + 1 + nameLength];
+ System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+ uniqueKey[declaringLength] = '.';
+ System.arraycopy(this.name, 0, uniqueKey, declaringLength + 1, nameLength);
+ return uniqueKey;
+}
+/**
+ * X t --> LX;
+ */
+public char[] genericSignature() {
+ if ((this.modifiers & AccGenericSignature) == 0) return null;
+ return this.type.genericTypeSignature();
+}
+
public final int getAccessFlags() {
return modifiers & AccJustFlag;
}
@@ -207,4 +243,26 @@ public final boolean isViewedAsDeprecated() {
public final boolean isVolatile() {
return (modifiers & AccVolatile) != 0;
}
+/**
+ * Returns the original field (as opposed to parameterized instances)
+ */
+public FieldBinding original() {
+ return this;
+}
+public FieldDeclaration sourceField() {
+ SourceTypeBinding sourceType;
+ try {
+ sourceType = (SourceTypeBinding) declaringClass;
+ } catch (ClassCastException e) {
+ return null;
+ }
+
+ FieldDeclaration[] fields = sourceType.scope.referenceContext.fields;
+ if (fields != null) {
+ for (int i = fields.length; --i >= 0;)
+ if (this == fields[i].binding)
+ return fields[i];
+ }
+ return null;
+}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
index 6eb0985..05c2992 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
@@ -18,7 +18,7 @@ public class ImportBinding extends Binding {
public boolean onDemand;
public ImportReference reference;
- Binding resolvedImport; // must ensure the import is resolved
+ public Binding resolvedImport; // must ensure the import is resolved
public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding, ImportReference reference) {
this.compoundName = compoundName;
@@ -30,9 +30,12 @@ public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding,
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
+public final int kind() {
return IMPORT;
}
+public boolean isStatic() {
+ return this.reference != null && this.reference.isStatic();
+}
public char[] readableName() {
if (onDemand)
return CharOperation.concat(CharOperation.concatWith(compoundName, '.'), ".*".toCharArray()); //$NON-NLS-1$
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java b/src/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
index e9703ba..462f95e 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
@@ -11,6 +11,8 @@
package org.eclipse.jdt.internal.compiler.lookup;
public interface InvocationSite {
+
+ TypeBinding[] genericTypeArguments();
boolean isSuperAccess();
boolean isTypeAccess();
void setDepth(int depth);
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
index cacc605..541448f 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
@@ -13,7 +13,6 @@ package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.util.Util;
public final class LocalTypeBinding extends NestedTypeBinding {
final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
@@ -65,7 +64,7 @@ public char[] constantPoolName() /* java/lang/Object */ {
ArrayBinding createArrayType(int dimensionCount) {
if (localArrayBindings == null) {
- localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount)};
+ localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount, scope.environment())};
return localArrayBindings[0];
}
@@ -77,33 +76,63 @@ ArrayBinding createArrayType(int dimensionCount) {
// no matching array
System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length);
- return localArrayBindings[length] = new ArrayBinding(this, dimensionCount);
+ return localArrayBindings[length] = new ArrayBinding(this, dimensionCount, scope.environment());
}
-public char[] readableName() {
+public char[] readableName() /*java.lang.Object, p.X */ {
+ char[] readableName;
if (isAnonymousType()) {
if (superInterfaces == NoSuperInterfaces)
- return ("<"+Util.bind("binding.subclass",new String(superclass.readableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.readableName(), TypeConstants.ANONYM_SUFFIX);
else
- return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].readableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ readableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].readableName(), TypeConstants.ANONYM_SUFFIX);
} else if (isMemberType()) {
- return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+ readableName = CharOperation.concat(enclosingType().readableName(), this.sourceName, '.');
} else {
- return sourceName;
+ readableName = this.sourceName;
+ }
+ TypeVariableBinding[] typeVars;
+ if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(readableName).append('<');
+ for (int i = 0, length = typeVars.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(typeVars[i].readableName());
+ }
+ nameBuffer.append('>');
+ int nameLength = nameBuffer.length();
+ readableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, readableName, 0);
}
+ return readableName;
}
-public char[] shortReadableName() {
+public char[] shortReadableName() /*Object*/ {
+ char[] shortReadableName;
if (isAnonymousType()) {
if (superInterfaces == NoSuperInterfaces)
- return ("<"+Util.bind("binding.subclass",new String(superclass.shortReadableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.shortReadableName(), TypeConstants.ANONYM_SUFFIX);
else
- return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].shortReadableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ shortReadableName = CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].shortReadableName(), TypeConstants.ANONYM_SUFFIX);
} else if (isMemberType()) {
- return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+ shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
} else {
- return sourceName;
+ shortReadableName = sourceName;
+ }
+ TypeVariableBinding[] typeVars;
+ if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(shortReadableName).append('<');
+ for (int i = 0, length = typeVars.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(typeVars[i].shortReadableName());
+ }
+ nameBuffer.append('>');
+ int nameLength = nameBuffer.length();
+ shortReadableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, shortReadableName, 0);
}
+ return shortReadableName;
}
// Record that the type is a local member type
@@ -117,11 +146,10 @@ public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Ob
public char[] sourceName() {
if (isAnonymousType()) {
- //return readableName();
if (superInterfaces == NoSuperInterfaces)
- return ("<"+Util.bind("binding.subclass",new String(superclass.sourceName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superclass.sourceName(), TypeConstants.ANONYM_SUFFIX);
else
- return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].sourceName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+ return CharOperation.concat(TypeConstants.ANONYM_PREFIX, superInterfaces[0].sourceName(), TypeConstants.ANONYM_SUFFIX);
} else
return sourceName;
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 0ab99f2..9084ae4 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -10,8 +10,11 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
public class LocalVariableBinding extends VariableBinding {
@@ -30,14 +33,11 @@ public class LocalVariableBinding extends VariableBinding {
public int initializationCount = 0;
// for synthetic local variables
+ // if declaration slot is not positionned, the variable will not be listed in attribute
+ // note that the name of a variable should be chosen so as not to conflict with user ones (usually starting with a space char is all needed)
public LocalVariableBinding(char[] name, TypeBinding type, int modifiers, boolean isArgument) {
-
- this.name = name;
- this.type = type;
- this.modifiers = modifiers;
+ super(name, type, modifiers, isArgument ? Constant.NotAConstant : null);
this.isArgument = isArgument;
- if (isArgument)
- this.constant = Constant.NotAConstant;
}
// regular local variable or argument
@@ -50,11 +50,56 @@ public class LocalVariableBinding extends VariableBinding {
/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
- public final int bindingType() {
+ public final int kind() {
return LOCAL;
}
+ /*
+ * declaringUniqueKey # scopeIndex / varName
+ * p.X { void foo() { int local; } } --> Lp/X;.foo()V#1/local
+ */
+ public char[] computeUniqueKey() {
+ StringBuffer buffer = new StringBuffer();
+
+ // declaring method or type
+ BlockScope scope = this.declaringScope;
+ MethodScope methodScope = scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
+ ReferenceContext referenceContext = methodScope.referenceContext;
+ if (referenceContext instanceof AbstractMethodDeclaration) {
+ MethodBinding methodBinding = ((AbstractMethodDeclaration) referenceContext).binding;
+ if (methodBinding != null) {
+ buffer.append(methodBinding.computeUniqueKey());
+ }
+ } else if (referenceContext instanceof TypeDeclaration) {
+ TypeBinding typeBinding = ((TypeDeclaration) referenceContext).binding;
+ if (typeBinding != null) {
+ buffer.append(typeBinding.computeUniqueKey());
+ }
+ }
+
+ // scope index
+ getScopeKey(scope, buffer);
+
+ // variable name
+ buffer.append('#');
+ buffer.append(this.name);
+
+ int length = buffer.length();
+ char[] uniqueKey = new char[length];
+ buffer.getChars(0, length, uniqueKey, 0);
+ return uniqueKey;
+ }
+
+ private void getScopeKey(BlockScope scope, StringBuffer buffer) {
+ int scopeIndex = scope.scopeIndex();
+ if (scopeIndex != -1) {
+ getScopeKey((BlockScope)scope.parent, buffer);
+ buffer.append('#');
+ buffer.append(scopeIndex);
+ }
+ }
+
// Answer whether the variable binding is a secret variable added for code gen purposes
public boolean isSecret() {
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index a7a9c9c..83b7380 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -10,51 +10,63 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.HashMap;
+import java.util.Map;
+
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
-import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
- public CompilerOptions options;
- public ProblemReporter problemReporter;
- public ITypeRequestor typeRequestor;
+ final static int BUILD_FIELDS_AND_METHODS = 4;
+ final static int BUILD_TYPE_HIERARCHY = 1;
+ final static int CHECK_AND_SET_IMPORTS = 2;
+ final static int CONNECT_TYPE_HIERARCHY = 3;
+ static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
+ static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
+
+ /**
+ * Map from typeBinding -> accessRestriction rule
+ */
+ private Map accessRestrictions;
+ ImportBinding[] defaultImports;
PackageBinding defaultPackage;
- ImportBinding[] defaultImports;
HashtableOfPackage knownPackages;
- static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
- static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
+ private int lastCompletedUnitIndex = -1;
+ private int lastUnitIndex = -1;
- private INameEnvironment nameEnvironment;
- private MethodVerifier verifier;
- private ArrayBinding[][] uniqueArrayBindings;
+ public INameEnvironment nameEnvironment;
+ public CompilerOptions options;
+ public ProblemReporter problemReporter;
- private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
- private int lastUnitIndex = -1;
- private int lastCompletedUnitIndex = -1;
- public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
+ // shared byte[]'s used by ClassFile to avoid allocating MBs during a build
+ public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated
+ public byte[] sharedClassFileContents = null;
+ public byte[] sharedClassFileHeader = null;
// indicate in which step on the compilation we are.
// step 1 : build the reference binding
// step 2 : conect the hierarchy (connect bindings)
// step 3 : build fields and method bindings.
private int stepCompleted;
- final static int BUILD_TYPE_HIERARCHY = 1;
- final static int CHECK_AND_SET_IMPORTS = 2;
- final static int CONNECT_TYPE_HIERARCHY = 3;
- final static int BUILD_FIELDS_AND_METHODS = 4;
+ public ITypeRequestor typeRequestor;
+ private ArrayBinding[][] uniqueArrayBindings;
+ private SimpleLookupTable uniqueParameterizedTypeBindings;
+ private SimpleLookupTable uniqueRawTypeBindings;
+ private SimpleLookupTable uniqueWildcardBindings;
+
+ public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
- // shared byte[]'s used by ClassFile to avoid allocating MBs during a build
- public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated
- public byte[] sharedClassFileHeader = null;
- public byte[] sharedClassFileContents = null;
+ private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
+ private MethodVerifier verifier;
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
this.typeRequestor = typeRequestor;
@@ -66,10 +78,16 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options,
this.knownPackages = new HashtableOfPackage();
this.uniqueArrayBindings = new ArrayBinding[5][];
this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
+ this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+ this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+ this.uniqueWildcardBindings = new SimpleLookupTable(3);
+ this.accessRestrictions = new HashMap(3);
}
-/* Ask the oracle for a type which corresponds to the compoundName.
-* Answer null if the name cannot be found.
-*/
+
+/**
+ * Ask the name environment for a type which corresponds to the compoundName.
+ * Answer null if the name cannot be found.
+ */
public ReferenceBinding askForType(char[][] compoundName) {
NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName);
@@ -78,13 +96,13 @@ public ReferenceBinding askForType(char[][] compoundName) {
if (answer.isBinaryType())
// the type was found as a .class file
- typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName));
+ typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName), answer.getAccessRestriction());
else if (answer.isCompilationUnit())
// the type was found as a .java file, try to build it then search the cache
- typeRequestor.accept(answer.getCompilationUnit());
+ typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
else if (answer.isSourceType())
// the type was found as a source model
- typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName));
+ typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName), answer.getAccessRestriction());
return getCachedType(compoundName);
}
@@ -104,13 +122,13 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
if (answer.isBinaryType())
// the type was found as a .class file
- typeRequestor.accept(answer.getBinaryType(), packageBinding);
+ typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction());
else if (answer.isCompilationUnit())
// the type was found as a .java file, try to build it then search the cache
- typeRequestor.accept(answer.getCompilationUnit());
+ typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
else if (answer.isSourceType())
// the type was found as a source model
- typeRequestor.accept(answer.getSourceTypes(), packageBinding);
+ typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
return packageBinding.getType0(name);
}
@@ -121,9 +139,9 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
* NOTE: This method can be called multiple times as additional source files are needed
*/
-public void buildTypeBindings(CompilationUnitDeclaration unit) {
+public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
CompilationUnitScope scope = new CompilationUnitScope(unit, this);
- scope.buildTypeBindings();
+ scope.buildTypeBindings(accessRestriction);
int unitsLength = units.length;
if (++lastUnitIndex >= unitsLength)
@@ -135,21 +153,21 @@ public void buildTypeBindings(CompilationUnitDeclaration unit) {
* Answer the created BinaryTypeBinding or null if the type is already in the cache.
*/
-public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType) {
- return cacheBinaryType(binaryType, true);
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
+ return cacheBinaryType(binaryType, true, accessRestriction);
}
/* Cache the binary type since we know it is needed during this compile.
*
* Answer the created BinaryTypeBinding or null if the type is already in the cache.
*/
-public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods) {
+public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
ReferenceBinding existingType = getCachedType(compoundName);
if (existingType == null || existingType instanceof UnresolvedReferenceBinding)
// only add the binary type if its not already in the cache
- return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods);
+ return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods, accessRestriction);
return null; // the type already exists & can be retrieved from the cache
}
/*
@@ -233,6 +251,67 @@ public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean
parsedUnit.scope.buildFieldsAndMethods();
this.unitBeingCompleted = null;
}
+public TypeBinding computeBoxingType(TypeBinding type) {
+ TypeBinding boxedType;
+ switch (type.id) {
+ case TypeIds.T_JavaLangBoolean :
+ return BooleanBinding;
+ case TypeIds.T_JavaLangByte :
+ return ByteBinding;
+ case TypeIds.T_JavaLangCharacter :
+ return CharBinding;
+ case TypeIds.T_JavaLangShort :
+ return ShortBinding;
+ case TypeIds.T_JavaLangDouble :
+ return DoubleBinding;
+ case TypeIds.T_JavaLangFloat :
+ return FloatBinding;
+ case TypeIds.T_JavaLangInteger :
+ return IntBinding;
+ case TypeIds.T_JavaLangLong :
+ return LongBinding;
+ case TypeIds.T_JavaLangVoid :
+ return VoidBinding;
+
+ case TypeIds.T_int :
+ boxedType = getType(JAVA_LANG_INTEGER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_INTEGER, NotFound);
+ case TypeIds.T_byte :
+ boxedType = getType(JAVA_LANG_BYTE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BYTE, NotFound);
+ case TypeIds.T_short :
+ boxedType = getType(JAVA_LANG_SHORT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_SHORT, NotFound);
+ case TypeIds.T_char :
+ boxedType = getType(JAVA_LANG_CHARACTER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_CHARACTER, NotFound);
+ case TypeIds.T_long :
+ boxedType = getType(JAVA_LANG_LONG);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_LONG, NotFound);
+ case TypeIds.T_float :
+ boxedType = getType(JAVA_LANG_FLOAT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_FLOAT, NotFound);
+ case TypeIds.T_double :
+ boxedType = getType(JAVA_LANG_DOUBLE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_DOUBLE, NotFound);
+ case TypeIds.T_boolean :
+ boxedType = getType(JAVA_LANG_BOOLEAN);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BOOLEAN, NotFound);
+ case TypeIds.T_void :
+ boxedType = getType(JAVA_LANG_VOID);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_VOID, NotFound);
+ }
+ return type;
+}
private PackageBinding computePackageFrom(char[][] constantPoolName) {
if (constantPoolName.length == 1)
return defaultPackage;
@@ -252,10 +331,10 @@ private PackageBinding computePackageFrom(char[][] constantPoolName) {
}
return packageBinding;
}
+
/* Used to guarantee array type identity.
*/
-
-ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
+public ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
return ((LocalTypeBinding) type).createArrayType(dimensionCount);
@@ -280,7 +359,7 @@ ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
while (++index < length) {
ArrayBinding currentBinding = arrayBindings[index];
if (currentBinding == null) // no matching array, but space left
- return arrayBindings[index] = new ArrayBinding(type, dimensionCount);
+ return arrayBindings[index] = new ArrayBinding(type, dimensionCount, this);
if (currentBinding.leafComponentType == type)
return currentBinding;
}
@@ -291,26 +370,26 @@ ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
(arrayBindings = new ArrayBinding[length * 2]), 0,
length);
uniqueArrayBindings[dimIndex] = arrayBindings;
- return arrayBindings[length] = new ArrayBinding(type, dimensionCount);
+ return arrayBindings[length] = new ArrayBinding(type, dimensionCount, this);
}
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) {
- return createBinaryTypeFrom(binaryType, packageBinding, true);
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
}
-public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) {
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);
-
+
// resolve any array bindings which reference the unresolvedType
ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
- if (cachedType != null) {
+ if (cachedType != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
+ // TODO (kent) suspect the check below is no longer required, since we should not be requesting a binary which is already in the cache
if (cachedType.isBinaryBinding()) // sanity check before the cast... at this point the cache should ONLY contain unresolved types
return (BinaryTypeBinding) cachedType;
- UnresolvedReferenceBinding unresolvedType = (UnresolvedReferenceBinding) cachedType;
- unresolvedType.resolvedType = binaryBinding;
- updateArrayCache(unresolvedType, binaryBinding);
+ ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
}
packageBinding.addType(binaryBinding);
+ setAccessRestriction(binaryBinding, accessRestriction);
binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
return binaryBinding;
}
@@ -348,13 +427,146 @@ PackageBinding createPackage(char[][] compoundName) {
}
return packageBinding;
}
-/* Answer the type for the compoundName if it exists in the cache.
-* Answer theNotFoundType if it could not be resolved the first time
-* it was looked up, otherwise answer null.
-*
-* NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
-* assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
-*/
+
+public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] originalArguments, ReferenceBinding enclosingType) {
+
+ // relocalize wildcard onto genericType (could come from other types)
+ TypeBinding[] typeArguments = originalArguments;
+ for (int i = 0, length = typeArguments == null ? 0 : typeArguments.length; i < length; i++) {
+ TypeBinding argument = originalArguments[i];
+ if (argument.isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) argument;
+ if (wildcard.genericType != genericType) { // wildcard comes from different type
+ if (typeArguments == originalArguments) {
+ System.arraycopy(originalArguments, 0, typeArguments = new TypeBinding[length], 0, i);
+ }
+ typeArguments[i] = createWildcard(genericType, i, wildcard.bound, wildcard.kind);
+ } else if (typeArguments != originalArguments) {
+ typeArguments[i] = argument;
+ }
+ } else if (typeArguments != originalArguments) {
+ typeArguments[i] = argument;
+ }
+ }
+
+ // cached info is array of already created parameterized types for this type
+ ParameterizedTypeBinding[] cachedInfo = (ParameterizedTypeBinding[])this.uniqueParameterizedTypeBindings.get(genericType);
+ int argLength = typeArguments == null ? 0: typeArguments.length;
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing parameterized for reusing one with same type arguments if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ ParameterizedTypeBinding cachedType = cachedInfo[i];
+ if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+ TypeBinding[] cachedArguments = cachedType.arguments;
+ int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length;
+ if (argLength != cachedArgLength) continue nextCachedType; // would be an error situation (from unresolved binaries)
+ for (int j = 0; j < cachedArgLength; j++){
+ if (typeArguments[j] != cachedArguments[j]) continue nextCachedType;
+ }
+ // all arguments match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new ParameterizedTypeBinding[1];
+ this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length+1], 0, length);
+ this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this);
+ cachedInfo[cachedInfo.length-1] = parameterizedType;
+ return parameterizedType;
+}
+
+public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
+ // cached info is array of already created raw types for this type
+ RawTypeBinding[] cachedInfo = (RawTypeBinding[])this.uniqueRawTypeBindings.get(genericType);
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing parameterized for reusing one with same type arguments if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ RawTypeBinding cachedType = cachedInfo[i];
+ if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
+ // all enclosing type match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new RawTypeBinding[1];
+ this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length+1], 0, length);
+ this.uniqueRawTypeBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this);
+ cachedInfo[cachedInfo.length-1] = rawType;
+ return rawType;
+
+}
+
+public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, int kind) {
+
+ // cached info is array of already created wildcard types for this type
+ WildcardBinding[] cachedInfo = (WildcardBinding[])this.uniqueWildcardBindings.get(genericType);
+ boolean needToGrow = false;
+ if (cachedInfo != null){
+ nextCachedType :
+ // iterate existing wildcards for reusing one with same information if any
+ for (int i = 0, max = cachedInfo.length; i < max; i++){
+ WildcardBinding cachedType = cachedInfo[i];
+ if (cachedType.genericType != genericType) continue nextCachedType; // remain of unresolved type
+ if (cachedType.rank != rank) continue nextCachedType;
+ if (cachedType.kind != kind) continue nextCachedType;
+ if (cachedType.bound != bound) continue nextCachedType;
+ // all match, reuse current
+ return cachedType;
+ }
+ needToGrow = true;
+ } else {
+ cachedInfo = new WildcardBinding[1];
+ this.uniqueWildcardBindings.put(genericType, cachedInfo);
+ }
+ // grow cache ?
+ if (needToGrow){
+ int length = cachedInfo.length;
+ System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length+1], 0, length);
+ this.uniqueWildcardBindings.put(genericType, cachedInfo);
+ }
+ // add new binding
+ WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, kind, this);
+ cachedInfo[cachedInfo.length-1] = wildcard;
+ return wildcard;
+}
+
+/**
+ * Returns the access restriction associated to a given type, or null if none
+ */
+public AccessRestriction getAccessRestriction(TypeBinding type) {
+ return (AccessRestriction) this.accessRestrictions.get(type);
+}
+
+/**
+ * Answer the type for the compoundName if it exists in the cache.
+ * Answer theNotFoundType if it could not be resolved the first time
+ * it was looked up, otherwise answer null.
+ *
+ * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
+ * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
+ */
public ReferenceBinding getCachedType(char[][] compoundName) {
if (compoundName.length == 1) {
@@ -405,7 +617,7 @@ PackageBinding getTopLevelPackage(char[] name) {
return null;
}
/* Answer the type corresponding to the compoundName.
-* Ask the oracle for the type if its not in the cache.
+* Ask the name environment for the type if its not in the cache.
* Answer null if the type cannot be found... likely a fatal error.
*/
@@ -444,14 +656,24 @@ public ReferenceBinding getType(char[][] compoundName) {
if (referenceBinding == null || referenceBinding == TheNotFoundType)
return null;
- if (referenceBinding instanceof UnresolvedReferenceBinding)
- referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this);
+ referenceBinding = BinaryTypeBinding.resolveType(referenceBinding, this, false); // no raw conversion for now
// compoundName refers to a nested type incorrectly (for example, package1.A$B)
if (referenceBinding.isNestedType())
return new ProblemReferenceBinding(compoundName, InternalNameProvided);
return referenceBinding;
}
+private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType) {
+ java.util.ArrayList args = new java.util.ArrayList(2);
+ int rank = 0;
+ do {
+ args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank++));
+ } while (wrapper.signature[wrapper.start] != '>');
+ wrapper.start++; // skip '>'
+ TypeBinding[] typeArguments = new TypeBinding[args.size()];
+ args.toArray(typeArguments);
+ return typeArguments;
+}
/* Answer the type corresponding to the name from the binary file.
* Does not ask the oracle for the type if its not found in the cache... instead an
* unresolved type is returned which must be resolved before used.
@@ -461,7 +683,7 @@ public ReferenceBinding getType(char[][] compoundName) {
* NOTE: Aborts compilation if the class file cannot be found.
*/
-ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) {
+ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized) {
if (end == -1)
end = signature.length;
@@ -474,6 +696,9 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
} else if (binding == TheNotFoundType) {
problemReporter.isClassPathCorrect(compoundName, null);
return null; // will not get here since the above error aborts the compilation
+ } else if (!isParameterized && binding.isGenericType()) {
+ // check raw type, only for resolved types
+ binding = createRawType(binding, binding.enclosingType());
}
return binding;
}
@@ -486,7 +711,7 @@ ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int en
* NOTE: Aborts compilation if the class file cannot be found.
*/
-TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
+TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType) {
int dimension = 0;
while (signature[start] == '[') {
start++;
@@ -527,19 +752,111 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
binding = ShortBinding;
break;
default :
- throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$
+ problemReporter.corruptedSignature(enclosingType, signature, start);
+ // will never reach here, since error will cause abort
}
} else {
- binding = getTypeFromConstantPoolName(signature, start + 1, end);
+ binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized); // skip leading 'L' or 'T'
}
if (dimension == 0)
return binding;
return createArrayType(binding, dimension);
}
+TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType) {
+ // TypeVariableSignature = 'T' Identifier ';'
+ // ArrayTypeSignature = '[' TypeSignature
+ // ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
+ // or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
+ // TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
+ int dimension = 0;
+ while (wrapper.signature[wrapper.start] == '[') {
+ wrapper.start++;
+ dimension++;
+ }
+
+ if (wrapper.signature[wrapper.start] == 'T') {
+ int varStart = wrapper.start + 1;
+ int varEnd = wrapper.computeEnd();
+ for (int i = staticVariables.length; --i >= 0;)
+ if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+ return dimension == 0 ? (TypeBinding) staticVariables[i] : createArrayType(staticVariables[i], dimension);
+ ReferenceBinding initialType = enclosingType;
+ do {
+ if (enclosingType instanceof BinaryTypeBinding) { // per construction can only be binary type binding
+ TypeVariableBinding[] enclosingVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables
+ for (int i = enclosingVariables.length; --i >= 0;)
+ if (CharOperation.equals(enclosingVariables[i].sourceName, wrapper.signature, varStart, varEnd))
+ return dimension == 0 ? (TypeBinding) enclosingVariables[i] : createArrayType(enclosingVariables[i], dimension);
+ }
+ } while ((enclosingType = enclosingType.enclosingType()) != null);
+ problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
+ return null; // cannot reach this, since previous problem will abort compilation
+ }
+ boolean isParameterized;
+ TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType);
+ if (!isParameterized)
+ return dimension == 0 ? type : createArrayType(type, dimension);
+
+ // type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
+ ReferenceBinding actualType = (ReferenceBinding) type;
+ TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType);
+ ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, null);
+
+ while (wrapper.signature[wrapper.start] == '.') {
+ wrapper.start++; // skip '.'
+ char[] memberName = wrapper.nextWord();
+ BinaryTypeBinding.resolveType(parameterizedType, this, false);
+ ReferenceBinding memberType = parameterizedType.type.getMemberType(memberName);
+ if (wrapper.signature[wrapper.start] == '<') {
+ wrapper.start++; // skip '<'
+ typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType);
+ } else {
+ typeArguments = null;
+ }
+ parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
+ }
+ wrapper.start++; // skip ';'
+ return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
+}
+TypeBinding getTypeFromVariantTypeSignature(
+ SignatureWrapper wrapper,
+ TypeVariableBinding[] staticVariables,
+ ReferenceBinding enclosingType,
+ ReferenceBinding genericType,
+ int rank) {
+ // VariantTypeSignature = '-' TypeSignature
+ // or '+' TypeSignature
+ // or TypeSignature
+ // or '*'
+ switch (wrapper.signature[wrapper.start]) {
+ case '-' :
+ // ? super aType
+ wrapper.start++;
+ TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ return createWildcard(genericType, rank, bound, Wildcard.SUPER);
+ case '+' :
+ // ? extends aType
+ wrapper.start++;
+ bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ return createWildcard(genericType, rank, bound, Wildcard.EXTENDS);
+ case '*' :
+ // ?
+ wrapper.start++;
+ return createWildcard(genericType, rank, null, Wildcard.UNBOUND);
+ default :
+ return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
+ }
+}
+public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
+ if (options.sourceLevel < ClassFileConstants.JDK1_5 || left.isBaseType() == right.isBaseType())
+ return false;
+
+ TypeBinding convertedType = computeBoxingType(left);
+ return convertedType == right || convertedType.isCompatibleWith(right);
+}
/* Ask the oracle if a package exists named name in the package named compoundName.
*/
-
boolean isPackage(char[][] compoundName, char[] name) {
if (compoundName == null || compoundName.length == 0)
return nameEnvironment.isPackage(null, name);
@@ -549,40 +866,66 @@ boolean isPackage(char[][] compoundName, char[] name) {
public MethodVerifier methodVerifier() {
if (verifier == null)
- verifier = new MethodVerifier(this);
+ verifier = this.options.sourceLevel < ClassFileConstants.JDK1_5
+ ? new MethodVerifier(this)
+ : new MethodVerifier15(this);
return verifier;
}
public void reset() {
this.defaultPackage = new PackageBinding(this); // assume the default package always exists
this.defaultImports = null;
this.knownPackages = new HashtableOfPackage();
+ this.accessRestrictions = new HashMap(3);
this.verifier = null;
- for (int i = this.uniqueArrayBindings.length; --i >= 0;)
- this.uniqueArrayBindings[i] = null;
- this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
-
+ for (int i = this.uniqueArrayBindings.length; --i >= 0;) {
+ ArrayBinding[] arrayBindings = this.uniqueArrayBindings[i];
+ if (arrayBindings != null)
+ for (int j = arrayBindings.length; --j >= 0;)
+ arrayBindings[j] = null;
+ }
+ this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
+ this.uniqueRawTypeBindings = new SimpleLookupTable(3);
+ this.uniqueWildcardBindings = new SimpleLookupTable(3);
+
for (int i = this.units.length; --i >= 0;)
this.units[i] = null;
this.lastUnitIndex = -1;
this.lastCompletedUnitIndex = -1;
this.unitBeingCompleted = null; // in case AbortException occurred
-
+
// name environment has a longer life cycle, and must be reset in
// the code which created it.
}
-void updateArrayCache(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
- nextDimension : for (int i = 0, length = uniqueArrayBindings.length; i < length; i++) {
- ArrayBinding[] arrayBindings = uniqueArrayBindings[i];
- if (arrayBindings != null) {
- for (int j = 0, max = arrayBindings.length; j < max; j++) {
- ArrayBinding currentBinding = arrayBindings[j];
- if (currentBinding == null)
- continue nextDimension;
- if (currentBinding.leafComponentType == unresolvedType) {
- currentBinding.leafComponentType = resolvedType;
- continue nextDimension;
- }
+/**
+ * Associate a given type with some access restriction
+ * (did not store the restriction directly into binding, since sparse information)
+ */
+public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
+ if (accessRestriction == null) return;
+ type.modifiers |= CompilerModifiers.AccRestrictedAccess;
+ this.accessRestrictions.put(type, accessRestriction);
+}
+
+void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
+ // walk all the unique collections & replace the unresolvedType with the resolvedType
+ // must prevent 2 entries so == still works (1 containing the unresolvedType and the other containing the resolvedType)
+ if (this.uniqueParameterizedTypeBindings.get(unresolvedType) != null) { // update the key
+ Object[] keys = this.uniqueParameterizedTypeBindings.keyTable;
+ for (int i = 0, l = keys.length; i < l; i++) {
+ if (keys[i] == unresolvedType) {
+ keys[i] = resolvedType; // hashCode is based on compoundName so this works - cannot be raw since type of parameterized type
+ break;
+ }
+ }
+ }
+
+ if (this.uniqueWildcardBindings.get(unresolvedType) != null) { // update the key
+ Object[] keys = this.uniqueWildcardBindings.keyTable;
+ for (int i = 0, l = keys.length; i < l; i++) {
+ if (keys[i] == unresolvedType) {
+ keys[i] = resolvedType; // hashCode is based on compoundName so this works
+ break;
}
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 0441fb3..f3e07f3 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -12,7 +12,7 @@ package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
public int modifiers;
@@ -21,20 +21,22 @@ public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
public TypeBinding[] parameters;
public ReferenceBinding[] thrownExceptions;
public ReferenceBinding declaringClass;
+ public TypeVariableBinding[] typeVariables = NoTypeVariables;
char[] signature;
-
+ public long tagBits;
+
protected MethodBinding() {
// for creating problem or synthetic method
}
-public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
this.modifiers = modifiers;
this.selector = selector;
this.returnType = returnType;
- this.parameters = (args == null || args.length == 0) ? NoParameters : args;
- this.thrownExceptions = (exceptions == null || exceptions.length == 0) ? NoExceptions : exceptions;
+ this.parameters = (parameters == null || parameters.length == 0) ? NoParameters : parameters;
+ this.thrownExceptions = (thrownExceptions == null || thrownExceptions.length == 0) ? NoExceptions : thrownExceptions;
this.declaringClass = declaringClass;
-
+
// propagate the strictfp & deprecated modifiers
if (this.declaringClass != null) {
if (this.declaringClass.isStrictfp())
@@ -44,8 +46,8 @@ public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, Typ
this.modifiers |= AccDeprecatedImplicitly;
}
}
-public MethodBinding(int modifiers, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
- this(modifiers, ConstructorDeclaration.ConstantPoolName, VoidBinding, args, exceptions, declaringClass);
+public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
+ this(modifiers, TypeConstants.INIT, VoidBinding, parameters, thrownExceptions, declaringClass);
}
// special API used to change method declaring class for runtime visibility check
public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
@@ -58,7 +60,6 @@ public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declar
}
/* Answer true if the argument types & the receiver's parameters are equal
*/
-
public final boolean areParametersEqual(MethodBinding method) {
TypeBinding[] args = method.parameters;
if (parameters == args)
@@ -73,12 +74,65 @@ public final boolean areParametersEqual(MethodBinding method) {
return false;
return true;
}
+public final boolean areParametersCompatibleWith(TypeBinding[] arguments) {
+ int paramLength = this.parameters.length;
+ int argLength = arguments.length;
+ int lastIndex = argLength;
+ if (isVarargs()) {
+ lastIndex = paramLength - 1;
+ if (paramLength == argLength) { // accept X[] but not X or X[][]
+ TypeBinding varArgType = parameters[lastIndex]; // is an ArrayBinding by definition
+ TypeBinding lastArgument = arguments[lastIndex];
+ if (varArgType != lastArgument && !lastArgument.isCompatibleWith(varArgType))
+ return false;
+ } else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
+ TypeBinding varArgType = ((ArrayBinding) parameters[lastIndex]).elementsType();
+ for (int i = lastIndex; i < argLength; i++)
+ if (varArgType != arguments[i] && !arguments[i].isCompatibleWith(varArgType))
+ return false;
+ } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
+ return false;
+ }
+ // now compare standard arguments from 0 to lastIndex
+ }
+ for (int i = 0; i < lastIndex; i++)
+ if (parameters[i] != arguments[i] && !arguments[i].isCompatibleWith(parameters[i]))
+ return false;
+ return true;
+}
+
+/* Answer true if the argument types & the receiver's parameters have the same erasure
+*/
+public final boolean areParameterErasuresEqual(MethodBinding method) {
+ TypeBinding[] args = method.parameters;
+ if (parameters == args)
+ return true;
+
+ int length = parameters.length;
+ if (length != args.length)
+ return false;
+
+ for (int i = 0; i < length; i++)
+ if (parameters[i] != args[i] && parameters[i].erasure() != args[i].erasure())
+ return false;
+ return true;
+}
/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
- return METHOD;
+public final int kind() {
+ return Binding.METHOD;
+}
+/* Answer true if the receiver is visible to the invocationPackage.
+*/
+
+public final boolean canBeSeenBy(PackageBinding invocationPackage) {
+ if (isPublic()) return true;
+ if (isPrivate()) return false;
+
+ // isProtected() or isDefault()
+ return invocationPackage == declaringClass.getPackage();
}
/* Answer true if the receiver is visible to the type provided by the scope.
* InvocationSite implements isSuperAccess() to provide additional information
@@ -111,7 +165,7 @@ public final boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
temp = temp.enclosingType();
}
- ReferenceBinding outerDeclaringClass = declaringClass;
+ ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
temp = outerDeclaringClass.enclosingType();
while (temp != null) {
outerDeclaringClass = temp;
@@ -173,7 +227,15 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
if (isPrivate()) {
// answer true if the receiverType is the declaringClass
// AND the invocationType and the declaringClass have a common enclosingType
- if (receiverType != declaringClass) return false;
+ receiverCheck: {
+ if (receiverType != declaringClass) {
+ // special tolerance for type variable direct bounds
+ if (receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(declaringClass.erasure())) {
+ break receiverCheck;
+ }
+ return false;
+ }
+ }
if (invocationType != declaringClass) {
ReferenceBinding outerInvocationType = invocationType;
@@ -183,7 +245,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
temp = temp.enclosingType();
}
- ReferenceBinding outerDeclaringClass = declaringClass;
+ ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringClass.erasure();
temp = outerDeclaringClass.enclosingType();
while (temp != null) {
outerDeclaringClass = temp;
@@ -208,6 +270,34 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
} while ((type = type.superclass()) != null);
return false;
}
+/*
+ * declaringUniqueKey dot selector genericSignature
+ * p.X { void bar(X t) } --> Lp/X;.bar(LX;)V
+ */
+public char[] computeUniqueKey() {
+ return computeUniqueKey(this);
+}
+protected char[] computeUniqueKey(MethodBinding methodBinding) {
+ // declaring class
+ char[] declaringKey = this.declaringClass.computeUniqueKey();
+ int declaringLength = declaringKey.length;
+
+ // selector
+ int selectorLength = this.selector == TypeConstants.INIT ? 0 : this.selector.length;
+
+ // generic signature
+ char[] sig = methodBinding.genericSignature();
+ if (sig == null) sig = methodBinding.signature();
+ int signatureLength = sig.length;
+
+ // compute unique key
+ char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength];
+ System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+ uniqueKey[declaringLength] = '.';
+ System.arraycopy(this.selector, 0, uniqueKey, declaringLength+1, selectorLength);
+ System.arraycopy(sig, 0, uniqueKey, declaringLength + 1 + selectorLength, signatureLength);
+ return uniqueKey;
+}
/*
* Answer the declaring class to use in the constant pool
* may not be a reference binding (see subtypes)
@@ -224,9 +314,71 @@ public TypeBinding constantPoolDeclaringClass() {
public final char[] constantPoolName() {
return selector;
}
+/**
+ *(param1 ... paramN)returnType thrownException1 ... thrownExceptionP
+ * T foo(T t) throws X ---> (TT;)TT;LX;
+ * void bar(X t) --> (LX;)V
+ * void bar(X t) --> (LX;)V
+ */
+public char[] genericSignature() {
+ if ((this.modifiers & AccGenericSignature) == 0) return null;
+ StringBuffer sig = new StringBuffer(10);
+ if (this.typeVariables != NoTypeVariables) {
+ sig.append('<');
+ for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+ sig.append(this.typeVariables[i].genericSignature());
+ }
+ sig.append('>');
+ }
+ sig.append('(');
+ for (int i = 0, length = this.parameters.length; i < length; i++) {
+ sig.append(this.parameters[i].genericTypeSignature());
+ }
+ sig.append(')');
+ if (this.returnType != null)
+ sig.append(this.returnType.genericTypeSignature());
+
+ // only append thrown exceptions if any is generic/parameterized
+ boolean needExceptionSignatures = false;
+ int length = this.thrownExceptions.length;
+ for (int i = 0; i < length; i++) {
+ if((this.thrownExceptions[i].modifiers & AccGenericSignature) != 0) {
+ needExceptionSignatures = true;
+ break;
+ }
+ }
+ if (needExceptionSignatures) {
+ for (int i = 0; i < length; i++) {
+ sig.append(this.thrownExceptions[i].genericTypeSignature());
+ }
+ }
+ int sigLength = sig.length();
+ char[] genericSignature = new char[sigLength];
+ sig.getChars(0, sigLength, genericSignature, 0);
+ return genericSignature;
+}
public final int getAccessFlags() {
return modifiers & AccJustFlag;
}
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+ for (int i = this.typeVariables.length; --i >= 0;)
+ if (CharOperation.equals(this.typeVariables[i].sourceName, variableName))
+ return this.typeVariables[i];
+ return null;
+}
+/**
+ * Returns true if method got substituted parameter types
+ * (see ParameterizedMethodBinding)
+ */
+public boolean hasSubstitutedParameters() {
+ return false;
+}
+
+/* Answer true if the return type got substituted.
+ */
+public boolean hasSubstitutedReturnType() {
+ return false;
+}
/* Answer true if the receiver is an abstract method
*/
@@ -243,10 +395,7 @@ public final boolean isBridge() {
/* Answer true if the receiver is a constructor
*/
public final boolean isConstructor() {
- return selector == ConstructorDeclaration.ConstantPoolName;
-}
-protected boolean isConstructorRelated() {
- return isConstructor();
+ return selector == TypeConstants.INIT;
}
/* Answer true if the receiver has default visibility
@@ -363,9 +512,9 @@ public final boolean isSynthetic() {
return (modifiers & AccSynthetic) != 0;
}
-/* Answer true if the receiver is a vararg method
+/* Answer true if the receiver method has varargs
*/
-public final boolean isVararg() {
+public final boolean isVarargs() {
return (modifiers & AccVarargs) != 0;
}
@@ -376,6 +525,13 @@ public final boolean isViewedAsDeprecated() {
(modifiers & AccDeprecatedImplicitly) != 0;
}
+/**
+ * Returns the original method (as opposed to parameterized instances)
+ */
+public MethodBinding original() {
+ return this;
+}
+
public char[] readableName() /* foo(int, Thread) */ {
StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
if (isConstructor())
@@ -412,7 +568,10 @@ public char[] shortReadableName() {
}
}
buffer.append(')');
- return buffer.toString().toCharArray();
+ int nameLength = buffer.length();
+ char[] shortReadableName = new char[nameLength];
+ buffer.getChars(0, nameLength, shortReadableName, 0);
+ return shortReadableName;
}
protected final void setSelector(char[] selector) {
@@ -434,9 +593,13 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
buffer.append('(');
TypeBinding[] targetParameters = this.parameters;
- boolean considerSynthetics = isConstructorRelated() && declaringClass.isNestedType();
- if (considerSynthetics) {
-
+ boolean isConstructor = isConstructor();
+ if (isConstructor && declaringClass.isEnum()) { // insert String name,int ordinal
+ buffer.append(ConstantPool.JavaLangStringSignature);
+ buffer.append(BaseTypes.IntBinding.signature());
+ }
+ boolean needSynthetics = isConstructor && declaringClass.isNestedType();
+ if (needSynthetics) {
// take into account the synthetic argument type signatures as well
ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
int count = syntheticArgumentTypes == null ? 0 : syntheticArgumentTypes.length;
@@ -444,8 +607,8 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
buffer.append(syntheticArgumentTypes[i].signature());
}
- if (this instanceof SyntheticAccessMethodBinding) {
- targetParameters = ((SyntheticAccessMethodBinding)this).targetMethod.parameters;
+ if (this instanceof SyntheticMethodBinding) {
+ targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters;
}
}
@@ -454,7 +617,7 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
buffer.append(targetParameters[i].signature());
}
}
- if (considerSynthetics) {
+ if (needSynthetics) {
SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables();
int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
for (int i = 0; i < count; i++) {
@@ -466,8 +629,13 @@ public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
}
}
buffer.append(')');
- buffer.append(returnType.signature());
- return signature = buffer.toString().toCharArray();
+ if (this.returnType != null)
+ buffer.append(this.returnType.signature());
+ int nameLength = buffer.length();
+ signature = new char[nameLength];
+ buffer.getChars(0, nameLength, signature, 0);
+
+ return signature;
}
public final int sourceEnd() {
AbstractMethodDeclaration method = sourceMethod();
@@ -475,7 +643,7 @@ public final int sourceEnd() {
return 0;
return method.sourceEnd;
}
-AbstractMethodDeclaration sourceMethod() {
+public AbstractMethodDeclaration sourceMethod() {
SourceTypeBinding sourceType;
try {
sourceType = (SourceTypeBinding) declaringClass;
@@ -495,6 +663,7 @@ public final int sourceStart() {
return 0;
return method.sourceStart;
}
+
/* During private access emulation, the binding can be requested to loose its
* private visibility when the class file is dumped.
*/
@@ -535,4 +704,14 @@ public String toString() {
}
return s;
}
+/**
+ * Returns the method to use during tiebreak (usually the method itself).
+ * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
+ */
+public MethodBinding tiebreakMethod() {
+ return this;
+}
+public TypeVariableBinding[] typeVariables() {
+ return this.typeVariables;
+}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/src/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 92b806b..67cf2dd 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
@@ -84,15 +85,11 @@ public class MethodScope extends BlockScope {
int unexpectedModifiers =
~(AccPublic | AccPrivate | AccProtected | AccStrictfp);
if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
else if (
(((AbstractMethodDeclaration) referenceContext).modifiers & AccStrictfp) != 0)
// must check the parse node explicitly
- problemReporter().illegalModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
// check for incompatible modifiers in the visibility bits, isolate the visibility bits
int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -104,19 +101,19 @@ public class MethodScope extends BlockScope {
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
+ modifiers &= ~AccProtected;
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
if ((accessorBits & AccProtected) != 0)
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
// if the receiver's declaring class is a private nested type, then make sure the receiver is not private (causes problems for inner type emulation)
if (methodBinding.declaringClass.isPrivate())
if ((modifiers & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
methodBinding.modifiers = modifiers;
}
@@ -134,12 +131,15 @@ public class MethodScope extends BlockScope {
// after this point, tests on the 16 bits reserved.
int realModifiers = modifiers & AccJustFlag;
- // set the requested modifiers for a method in an interface
- if (methodBinding.declaringClass.isInterface()) {
- if ((realModifiers & ~(AccPublic | AccAbstract)) != 0)
- problemReporter().illegalModifierForInterfaceMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ // set the requested modifiers for a method in an interface/annotation
+ if ((methodBinding.declaringClass.modifiers & AccInterface) != 0) {
+ if ((realModifiers & ~(AccPublic | AccAbstract)) != 0) {
+ if ((methodBinding.declaringClass.modifiers & AccAnnotation) != 0) {
+ problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext);
+ } else {
+ problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext);
+ }
+ }
return;
}
@@ -156,9 +156,7 @@ public class MethodScope extends BlockScope {
| AccNative
| AccStrictfp);
if ((realModifiers & unexpectedModifiers) != 0)
- problemReporter().illegalModifierForMethod(
- methodBinding.declaringClass,
- (AbstractMethodDeclaration) referenceContext);
+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
// check for incompatible modifiers in the visibility bits, isolate the visibility bits
int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
@@ -170,13 +168,13 @@ public class MethodScope extends BlockScope {
// need to keep the less restrictive
if ((accessorBits & AccPublic) != 0) {
if ((accessorBits & AccProtected) != 0)
- modifiers ^= AccProtected;
+ modifiers &= ~AccProtected;
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
if ((accessorBits & AccProtected) != 0)
if ((accessorBits & AccPrivate) != 0)
- modifiers ^= AccPrivate;
+ modifiers &= ~AccPrivate;
}
// check for modifiers incompatible with abstract modifier
@@ -300,19 +298,38 @@ public class MethodScope extends BlockScope {
SourceTypeBinding declaringClass = referenceType().binding;
int modifiers = method.modifiers | AccUnresolved;
if (method.isConstructor()) {
- if (method.isDefaultConstructor()) {
+ if (method.isDefaultConstructor())
modifiers |= AccIsDefaultConstructor;
- }
method.binding = new MethodBinding(modifiers, null, null, declaringClass);
checkAndSetModifiersForConstructor(method.binding);
} else {
- if (declaringClass.isInterface())
+ if ((declaringClass.modifiers & AccInterface) != 0) // interface or annotation type
modifiers |= AccPublic | AccAbstract;
method.binding =
new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
checkAndSetModifiersForMethod(method.binding);
}
this.isStatic = method.binding.isStatic();
+
+ Argument[] argTypes = method.arguments;
+ int argLength = argTypes == null ? 0 : argTypes.length;
+ if (argLength > 0 && environment().options.sourceLevel >= ClassFileConstants.JDK1_5) {
+ if (argTypes[--argLength].isVarArgs())
+ method.binding.modifiers |= AccVarargs;
+ while (--argLength >= 0) {
+ if (argTypes[argLength].isVarArgs())
+ problemReporter().illegalVararg(argTypes[argLength], method);
+ }
+ }
+
+ TypeParameter[] typeParameters = method.typeParameters();
+ // do not construct type variables if source < 1.5
+ if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) {
+ method.binding.typeVariables = NoTypeVariables;
+ } else {
+ method.binding.typeVariables = createTypeVariables(typeParameters, method.binding);
+ method.binding.modifiers |= AccGenericSignature;
+ }
return method.binding;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
index 115864c..e47cdd3 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
@@ -10,13 +10,13 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-public final class MethodVerifier implements TagBits, TypeConstants {
+public class MethodVerifier implements TagBits, TypeConstants {
SourceTypeBinding type;
HashtableOfObject inheritedMethods;
HashtableOfObject currentMethods;
@@ -40,7 +40,7 @@ Binding creation is responsible for reporting all problems with types:
- defining a static class or interface inside a non-static nested class
- defining an interface as a local type (local types can only be classes)
*/
-public MethodVerifier(LookupEnvironment environment) {
+MethodVerifier(LookupEnvironment environment) {
this.type = null; // Initialized with the public method verify(SourceTypeBinding)
this.inheritedMethods = null;
this.currentMethods = null;
@@ -48,7 +48,10 @@ public MethodVerifier(LookupEnvironment environment) {
this.errorException = null;
this.environment = environment;
}
-private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
+boolean areMethodsEqual(MethodBinding one, MethodBinding two) {
+ return areParametersEqual(one, two);
+}
+boolean areParametersEqual(MethodBinding one, MethodBinding two) {
TypeBinding[] oneArgs = one.parameters;
TypeBinding[] twoArgs = two.parameters;
if (oneArgs == twoArgs) return true;
@@ -60,51 +63,79 @@ private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
return true;
}
-private boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
+boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
return areTypesEqual(one.returnType, two.returnType);
}
-private boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+boolean canSkipInheritedMethods() {
+ if (this.type.superclass() != null && this.type.superclass().isAbstract())
+ return false;
+ return this.type.superInterfaces() == NoSuperInterfaces;
+}
+boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) {
+ return two == null // already know one is not null
+ || one.declaringClass == two.declaringClass;
+}
+boolean areTypesEqual(TypeBinding one, TypeBinding two) {
if (one == two) return true;
- if (one instanceof ReferenceBinding && two instanceof ReferenceBinding)
- // can compare unresolved to resolved reference bindings
- return CharOperation.equals(((ReferenceBinding) one).compoundName, ((ReferenceBinding) two).compoundName);
+
+ // its possible that an UnresolvedReferenceBinding can be compared to its resolved type
+ // when they're both UnresolvedReferenceBindings then they must be identical like all other types
+ // all wrappers of UnresolvedReferenceBindings are converted as soon as the type is resolved
+ // so its not possible to have 2 arrays where one is UnresolvedX[] and the other is X[]
+ if (one instanceof UnresolvedReferenceBinding)
+ return ((UnresolvedReferenceBinding) one).resolvedType == two;
+ if (two instanceof UnresolvedReferenceBinding)
+ return ((UnresolvedReferenceBinding) two).resolvedType == one;
return false; // all other type bindings are identical
}
-private void checkAbstractMethod(MethodBinding abstractMethod) {
- if (mustImplementAbstractMethod(abstractMethod)) {
+void checkAbstractMethod(MethodBinding abstractMethod) {
+ if (mustImplementAbstractMethod(abstractMethod.declaringClass)) {
TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
if (typeDeclaration != null) {
MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(abstractMethod);
missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
} else {
- this.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+ problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
}
}
}
-private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+ boolean isAnnotationMember = this.type.isAnnotationType();
nextMethod : for (int i = length; --i >= 0;) {
MethodBinding inheritedMethod = methods[i];
if (currentMethod.isStatic() != inheritedMethod.isStatic()) { // Cannot override a static method or hide an instance method
- this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+ problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
continue nextMethod;
}
- if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
- if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
+ if (inheritedMethod.isAbstract()) {
+ if (inheritedMethod.declaringClass.isInterface()) {
currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+ } else {
+ currentMethod.modifiers |= CompilerModifiers.AccImplementing | CompilerModifiers.AccOverriding;
+ }
+// with the above change an abstract method is tagged as implementing the inherited abstract method
+// if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
+// if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
+// currentMethod.modifiers |= CompilerModifiers.AccImplementing;
} else {
currentMethod.modifiers |= CompilerModifiers.AccOverriding;
}
+ if (isAnnotationMember) {
+ // annotation cannot override any method
+ problemReporter().annotationCannotOverrideMethod(currentMethod, inheritedMethod);
+ return; // do not repoort against subsequent inherited methods
+ }
if (!areReturnTypesEqual(currentMethod, inheritedMethod)) {
- this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
+ problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
} else {
if (currentMethod.thrownExceptions != NoExceptions)
- this.checkExceptions(currentMethod, inheritedMethod);
+ checkExceptions(currentMethod, inheritedMethod);
if (inheritedMethod.isFinal())
- this.problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
- if (!this.isAsVisible(currentMethod, inheritedMethod))
- this.problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
+ problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
+ if (!isAsVisible(currentMethod, inheritedMethod))
+ problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
if (environment.options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) {
if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode) {
// check against the other inherited methods to see if they hide this inheritedMethod
@@ -114,9 +145,10 @@ private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBin
if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
continue nextMethod;
- this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
+ problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
}
}
+ checkForBridgeMethod(currentMethod, inheritedMethod);
}
}
}
@@ -126,24 +158,27 @@ Verify that newExceptions are all included in inheritedExceptions.
Assumes all exceptions are valid and throwable.
Unchecked exceptions (compatible with runtime & error) are ignored (see the spec on pg. 203).
*/
-private void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
+void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
ReferenceBinding[] newExceptions = resolvedExceptionTypesFor(newMethod);
ReferenceBinding[] inheritedExceptions = resolvedExceptionTypesFor(inheritedMethod);
for (int i = newExceptions.length; --i >= 0;) {
ReferenceBinding newException = newExceptions[i];
int j = inheritedExceptions.length;
- while (--j > -1 && !this.isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/}
+ while (--j > -1 && !isSameClassOrSubclassOf(newException, inheritedExceptions[j])){/*empty*/}
if (j == -1)
- if (!(newException.isCompatibleWith(this.runtimeException()) || newException.isCompatibleWith(this.errorException())))
- this.problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
+ if (!(newException.isCompatibleWith(runtimeException()) || newException.isCompatibleWith(errorException())))
+ problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
}
}
-private void checkInheritedMethods(MethodBinding[] methods, int length) {
+void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+ // no op before 1.5
+}
+void checkInheritedMethods(MethodBinding[] methods, int length) {
MethodBinding first = methods[0];
int index = length;
while (--index > 0 && areReturnTypesEqual(first, methods[index])){/*empty*/}
if (index > 0) { // All inherited methods do NOT have the same vmSignature
- this.problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
+ problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
return;
}
@@ -159,13 +194,13 @@ private void checkInheritedMethods(MethodBinding[] methods, int length) {
if (concreteMethod == null) {
if (this.type.isClass() && !this.type.isAbstract()) {
for (int i = length; --i >= 0;) {
- if (mustImplementAbstractMethod(methods[i])) {
+ if (mustImplementAbstractMethod(methods[i].declaringClass)) {
TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
if (typeDeclaration != null) {
MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
} else {
- this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+ problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
}
return;
}
@@ -183,13 +218,13 @@ private void checkInheritedMethods(MethodBinding[] methods, int length) {
// Remember that interfaces can only define public instance methods
if (concreteMethod.isStatic())
// Cannot inherit a static method which is specified as an instance method by an interface
- this.problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods);
+ problemReporter().staticInheritedMethodConflicts(type, concreteMethod, abstractMethods);
if (!concreteMethod.isPublic())
// Cannot reduce visibility of a public method specified by an interface
- this.problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
+ problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
if (concreteMethod.thrownExceptions != NoExceptions)
for (int i = abstractMethods.length; --i >= 0;)
- this.checkExceptions(concreteMethod, abstractMethods[i]);
+ checkExceptions(concreteMethod, abstractMethods[i]);
}
/*
For each inherited method identifier (message pattern - vm signature minus the return type)
@@ -209,10 +244,9 @@ For each inherited method identifier (message pattern - vm signature minus the r
else
complain about missing implementation only if type is NOT an interface or abstract
*/
-private void checkMethods() {
- boolean mustImplementAbstractMethods = this.type.isClass() && !this.type.isAbstract();
- boolean skipInheritedMethods = mustImplementAbstractMethods && this.type.superInterfaces() == NoSuperInterfaces
- && this.type.superclass() != null && !this.type.superclass().isAbstract(); // have a single concrete superclass so only check overridden methods
+void checkMethods() {
+ boolean mustImplementAbstractMethods = ((this.type.modifiers & IConstants.AccInterface) == 0) && !this.type.isAbstract();
+ boolean skipInheritedMethods = mustImplementAbstractMethods && canSkipInheritedMethods(); // have a single concrete superclass so only check overridden methods
char[][] methodSelectors = this.inheritedMethods.keyTable;
nextSelector : for (int s = methodSelectors.length; --s >= 0;) {
if (methodSelectors[s] == null) continue nextSelector;
@@ -236,13 +270,16 @@ private void checkMethods() {
MethodBinding currentMethod = current[i];
for (int j = 0, length2 = inherited.length; j < length2; j++) {
MethodBinding inheritedMethod = inherited[j];
- if (inheritedMethod != null && areParametersEqual(currentMethod, inheritedMethod)) {
- matchingInherited[++index] = inheritedMethod;
- inherited[j] = null; // do not want to find it again
+ if (inheritedMethod != null) {
+ inheritedMethod = computeSubstituteMethod(inheritedMethod, currentMethod);
+ if (areMethodsEqual(currentMethod, inheritedMethod)) {
+ matchingInherited[++index] = inheritedMethod;
+ inherited[j] = null; // do not want to find it again
+ }
}
}
if (index >= 0)
- this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+ checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
}
}
@@ -252,39 +289,48 @@ private void checkMethods() {
if (inheritedMethod != null) {
matchingInherited[++index] = inheritedMethod;
for (int j = i + 1; j < length; j++) {
- if (inherited[j] != null && areParametersEqual(inheritedMethod, inherited[j])) {
- matchingInherited[++index] = inherited[j];
+ MethodBinding otherInheritedMethod = inherited[j];
+ if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod))
+ continue;
+ otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
+ if (areMethodsEqual(inheritedMethod, otherInheritedMethod)) {
+ matchingInherited[++index] = otherInheritedMethod;
inherited[j] = null; // do not want to find it again
}
}
}
if (index > 0)
- this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
+ checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
checkAbstractMethod(matchingInherited[0]);
}
}
}
-private void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+ // check that the inherited abstract method (package private visibility) is implemented within the same package
+ PackageBinding necessaryPackage = abstractMethod.declaringClass.fPackage;
+ if (necessaryPackage == this.type.fPackage) return; // not a problem
+
ReferenceBinding superType = this.type.superclass();
char[] selector = abstractMethod.selector;
do {
if (!superType.isValidBinding()) return;
if (!superType.isAbstract()) return; // closer non abstract super type will be flagged instead
- MethodBinding[] methods = superType.getMethods(selector);
- nextMethod : for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (!areReturnTypesEqual(method, abstractMethod) || !areParametersEqual(method, abstractMethod))
- continue nextMethod;
- if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
- continue nextMethod;
- if (superType.fPackage == abstractMethod.declaringClass.fPackage) return; // found concrete implementation of abstract method in same package
+ if (necessaryPackage == superType.fPackage) {
+ MethodBinding[] methods = superType.getMethods(selector);
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
+ continue nextMethod;
+ if (doesMethodOverride(method, abstractMethod))
+ return; // found concrete implementation of abstract method in same package
+ }
}
} while ((superType = superType.superclass()) != abstractMethod.declaringClass);
// non visible abstract methods cannot be overridden so the type must be defined abstract
- this.problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod);
+ problemReporter().abstractMethodCannotBeOverridden(this.type, abstractMethod);
}
/*
Binding creation is responsible for reporting:
@@ -298,7 +344,10 @@ Binding creation is responsible for reporting:
- check the type of any array is not void
- check that each exception type is Throwable or a subclass of it
*/
-private void computeInheritedMethods() {
+void computeInheritedMethods() {
+ // only want to remember inheritedMethods that can have an impact on the current type
+ // if an inheritedMethod has been 'replaced' by a supertype's method then skip it
+
this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[3][];
int lastPosition = -1;
@@ -306,83 +355,81 @@ private void computeInheritedMethods() {
if (itsInterfaces != NoSuperInterfaces)
interfacesToVisit[++lastPosition] = itsInterfaces;
- ReferenceBinding superType = this.type.isClass()
- ? this.type.superclass()
+ ReferenceBinding superType = (this.type.modifiers & IConstants.AccInterface) == 0
+ ? this.type.superclass() // class or enum
: this.type.scope.getJavaLangObject(); // check interface methods against Object
HashtableOfObject nonVisibleDefaultMethods = new HashtableOfObject(3); // maps method selectors to an array of methods
boolean allSuperclassesAreAbstract = true;
- while (superType != null) {
- if (superType.isValidBinding()) {
- if (allSuperclassesAreAbstract) {
- if (superType.isAbstract()) {
- // only need to include superinterfaces if immediate superclasses are abstract
- if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
- if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
- interfacesToVisit[lastPosition] = itsInterfaces;
- }
- } else {
- allSuperclassesAreAbstract = false;
+ while (superType != null && superType.isValidBinding()) {
+ if (allSuperclassesAreAbstract) {
+ if (superType.isAbstract()) {
+ // only need to include superinterfaces if immediate superclasses are abstract
+ if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
}
+ } else {
+ allSuperclassesAreAbstract = false;
}
+ }
- MethodBinding[] methods = superType.unResolvedMethods();
- nextMethod : for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
- continue nextMethod;
- MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
- if (existingMethods != null) {
- for (int i = 0, length = existingMethods.length; i < length; i++) {
- if (areReturnTypesEqual(method, existingMethods[i]) && areParametersEqual(method, existingMethods[i])) {
- if (method.isDefault() && method.isAbstract() && method.declaringClass.fPackage != type.fPackage)
- checkPackagePrivateAbstractMethod(method);
- continue nextMethod;
- }
+ MethodBinding[] methods = superType.unResolvedMethods();
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding inheritedMethod = methods[m];
+ if (inheritedMethod.isPrivate() || inheritedMethod.isConstructor() || inheritedMethod.isDefaultAbstract())
+ continue nextMethod;
+ MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
+ if (existingMethods != null) {
+ for (int i = 0, length = existingMethods.length; i < length; i++) {
+ if (existingMethods[i].declaringClass != inheritedMethod.declaringClass && doesMethodOverride(existingMethods[i], inheritedMethod)) {
+ if (inheritedMethod.isDefault() && inheritedMethod.isAbstract())
+ checkPackagePrivateAbstractMethod(inheritedMethod);
+ continue nextMethod;
}
}
- MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(method.selector);
- if (nonVisible != null)
- for (int i = 0, l = nonVisible.length; i < l; i++)
- if (areReturnTypesEqual(method, nonVisible[i]) && areParametersEqual(method, nonVisible[i]))
- continue nextMethod;
-
- if (!method.isDefault() || method.declaringClass.fPackage == type.fPackage) {
- if (existingMethods == null) {
- existingMethods = new MethodBinding[] {method};
- } else {
- int length = existingMethods.length;
- System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
- existingMethods[length] = method;
- }
- this.inheritedMethods.put(method.selector, existingMethods);
+ }
+ MethodBinding[] nonVisible = (MethodBinding[]) nonVisibleDefaultMethods.get(inheritedMethod.selector);
+ if (nonVisible != null)
+ for (int i = 0, l = nonVisible.length; i < l; i++)
+ if (doesMethodOverride(nonVisible[i], inheritedMethod))
+ continue nextMethod;
+
+ if (!inheritedMethod.isDefault() || inheritedMethod.declaringClass.fPackage == type.fPackage) {
+ if (existingMethods == null) {
+ existingMethods = new MethodBinding[] {inheritedMethod};
} else {
- if (nonVisible == null) {
- nonVisible = new MethodBinding[] {method};
- } else {
- int length = nonVisible.length;
- System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length);
- nonVisible[length] = method;
- }
- nonVisibleDefaultMethods.put(method.selector, nonVisible);
-
- if (method.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
- this.problemReporter().abstractMethodCannotBeOverridden(this.type, method);
-
- MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(method.selector);
- if (current != null) { // non visible methods cannot be overridden so a warning is issued
- foundMatch : for (int i = 0, length = current.length; i < length; i++) {
- if (areReturnTypesEqual(method, current[i]) && areParametersEqual(method, current[i])) {
- this.problemReporter().overridesPackageDefaultMethod(current[i], method);
- break foundMatch;
- }
+ int length = existingMethods.length;
+ System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
+ existingMethods[length] = inheritedMethod;
+ }
+ this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
+ } else {
+ if (nonVisible == null) {
+ nonVisible = new MethodBinding[] {inheritedMethod};
+ } else {
+ int length = nonVisible.length;
+ System.arraycopy(nonVisible, 0, nonVisible = new MethodBinding[length + 1], 0, length);
+ nonVisible[length] = inheritedMethod;
+ }
+ nonVisibleDefaultMethods.put(inheritedMethod.selector, nonVisible);
+
+ if (inheritedMethod.isAbstract() && !this.type.isAbstract()) // non visible abstract methods cannot be overridden so the type must be defined abstract
+ problemReporter().abstractMethodCannotBeOverridden(this.type, inheritedMethod);
+
+ MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(inheritedMethod.selector);
+ if (current != null) { // non visible methods cannot be overridden so a warning is issued
+ foundMatch : for (int i = 0, length = current.length; i < length; i++) {
+ if (doesMethodOverride(current[i], inheritedMethod)) {
+ problemReporter().overridesPackageDefaultMethod(current[i], inheritedMethod);
+ break foundMatch;
}
}
}
}
- superType = superType.superclass();
}
+ superType = superType.superclass();
}
for (int i = 0; i <= lastPosition; i++) {
@@ -400,21 +447,20 @@ private void computeInheritedMethods() {
MethodBinding[] methods = superType.unResolvedMethods();
nextMethod : for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
- MethodBinding method = methods[m];
- MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
+ MethodBinding inheritedMethod = methods[m];
+ MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(inheritedMethod.selector);
if (existingMethods == null) {
- existingMethods = new MethodBinding[] {method};
+ existingMethods = new MethodBinding[] {inheritedMethod};
} else {
int length = existingMethods.length;
- for (int e = 0; e < length; e++) {
- MethodBinding existing = existingMethods[e];
- if (areParametersEqual(method, existing) && existing.declaringClass.implementsInterface(superType, true))
+ // look to see if any of the existingMethods implement this inheritedMethod
+ for (int e = 0; e < length; e++)
+ if (isInterfaceMethodImplemented(inheritedMethod, existingMethods[e], superType))
continue nextMethod; // skip interface method with the same signature if visible to its declaringClass
- }
System.arraycopy(existingMethods, 0, existingMethods = new MethodBinding[length + 1], 0, length);
- existingMethods[length] = method;
+ existingMethods[length] = inheritedMethod;
}
- this.inheritedMethods.put(method.selector, existingMethods);
+ this.inheritedMethods.put(inheritedMethod.selector, existingMethods);
}
}
}
@@ -428,7 +474,7 @@ private void computeInheritedMethods() {
interfaces[j].tagBits &= ~InterfaceVisited;
}
}
-private void computeMethods() {
+void computeMethods() {
MethodBinding[] methods = type.methods();
int size = methods.length;
this.currentMethods = new HashtableOfObject(size == 0 ? 1 : size); // maps method selectors to an array of methods... must search to match paramaters & return type
@@ -446,12 +492,18 @@ private void computeMethods() {
}
}
}
-private ReferenceBinding errorException() {
+MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
+ return inheritedMethod;
+}
+public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
+ return areReturnTypesEqual(method, inheritedMethod) && areParametersEqual(method, inheritedMethod);
+}
+ReferenceBinding errorException() {
if (errorException == null)
this.errorException = this.type.scope.getJavaLangError();
return errorException;
}
-private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
+boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
if (inheritedMethod.modifiers == newMethod.modifiers) return true;
if (newMethod.isPublic()) return true; // Covers everything
@@ -462,17 +514,20 @@ private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMeth
return !newMethod.isPrivate(); // The inheritedMethod cannot be private since it would not be visible
}
-private boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
+boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
+ // skip interface method with the same signature if visible to its declaringClass
+ return areParametersEqual(existingMethod, inheritedMethod) && existingMethod.declaringClass.implementsInterface(superType, true);
+}
+boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
do {
if (testClass == superclass) return true;
} while ((testClass = testClass.superclass()) != null);
return false;
}
-private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
+boolean mustImplementAbstractMethod(ReferenceBinding declaringClass) {
// if the type's superclass is an abstract class, then all abstract methods must be implemented
// otherwise, skip it if the type's superclass must implement any of the inherited methods
ReferenceBinding superclass = this.type.superclass();
- ReferenceBinding declaringClass = abstractMethod.declaringClass;
if (declaringClass.isClass()) {
while (superclass.isAbstract() && superclass != declaringClass)
superclass = superclass.superclass(); // find the first concrete superclass or the abstract declaringClass
@@ -487,10 +542,10 @@ private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
}
return superclass.isAbstract(); // if it is a concrete class then we have already reported problem against it
}
-private ProblemReporter problemReporter() {
+ProblemReporter problemReporter() {
return this.type.scope.problemReporter();
}
-private ProblemReporter problemReporter(MethodBinding currentMethod) {
+ProblemReporter problemReporter(MethodBinding currentMethod) {
ProblemReporter reporter = problemReporter();
if (currentMethod.declaringClass == type) // only report against the currentMethod if its implemented by the type
reporter.referenceContext = currentMethod.sourceMethod();
@@ -503,23 +558,21 @@ ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) {
if (!(method.declaringClass instanceof BinaryTypeBinding))
return TypeConstants.NoExceptions; // safety check
- BinaryTypeBinding binaryType = (BinaryTypeBinding) method.declaringClass;
for (int i = exceptions.length; --i >= 0;)
- if (exceptions[i] instanceof UnresolvedReferenceBinding)
- exceptions[i] = (ReferenceBinding) binaryType.resolveType(exceptions[i]);
+ exceptions[i] = BinaryTypeBinding.resolveType(exceptions[i], this.environment, true);
return exceptions;
}
-private ReferenceBinding runtimeException() {
+ReferenceBinding runtimeException() {
if (runtimeException == null)
this.runtimeException = this.type.scope.getJavaLangRuntimeException();
return runtimeException;
}
-public void verify(SourceTypeBinding someType) {
+void verify(SourceTypeBinding someType) {
this.type = someType;
- this.computeMethods();
- this.computeInheritedMethods();
- this.checkMethods();
+ computeMethods();
+ computeInheritedMethods();
+ checkMethods();
}
public String toString() {
StringBuffer buffer = new StringBuffer(10);
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
new file mode 100644
index 0000000..cec3089
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+
+class MethodVerifier15 extends MethodVerifier {
+
+MethodVerifier15(LookupEnvironment environment) {
+ super(environment);
+}
+boolean areMethodsEqual(MethodBinding one, MethodBinding substituteTwo) {
+ TypeBinding[] oneParams = one.parameters;
+ TypeBinding[] twoParams = substituteTwo.parameters;
+ boolean checkParameters = false;
+ if (oneParams != twoParams) {
+ int length = oneParams.length;
+ if (length != twoParams.length) return false; // no match
+
+ for (int i = 0; i < length; i++) {
+ if (oneParams[i] != twoParams[i]) {
+ checkParameters |= oneParams[i].leafComponentType().isParameterizedType();
+ if (!areTypesEqual(oneParams[i], twoParams[i])) {
+ while (!checkParameters && ++i < length)
+ checkParameters |= oneParams[i].leafComponentType().isParameterizedType();
+ if (one.areParameterErasuresEqual(substituteTwo)) // at least one parameter may cause a name clash
+ detectNameClash(one, substituteTwo, checkParameters);
+ return false; // no match but needed to check for a name clash
+ }
+ }
+ }
+ }
+ return !detectNameClash(one, substituteTwo, checkParameters);
+}
+boolean areReturnTypesEqual(MethodBinding one, MethodBinding substituteTwo) {
+ if (one.returnType == substituteTwo.returnType) return true;
+
+ // methods from classes are always before methods from interfaces
+ if (one.declaringClass.isClass() || one.declaringClass.implementsInterface(substituteTwo.declaringClass, true))
+ return one.returnType.isCompatibleWith(substituteTwo.returnType);
+
+ if (substituteTwo.declaringClass.implementsInterface(one.declaringClass, true))
+ return substituteTwo.returnType.isCompatibleWith(one.returnType);
+
+ // unrelated interfaces... one must be a subtype of the other
+ return one.returnType.isCompatibleWith(substituteTwo.returnType)
+ || substituteTwo.returnType.isCompatibleWith(one.returnType);
+}
+boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+ if (one == two) return true;
+
+ switch (one.kind()) {
+ case Binding.PARAMETERIZED_TYPE :
+ case Binding.RAW_TYPE :
+ return one.isEquivalentTo(two);
+// case Binding.TYPE_PARAMETER : // won't work for variables from different classes - need substitution
+ }
+
+ // Can skip this since we resolved each method before comparing it, see computeSubstituteMethod()
+ // if (one instanceof UnresolvedReferenceBinding)
+ // return ((UnresolvedReferenceBinding) one).resolvedType == two;
+ // if (two instanceof UnresolvedReferenceBinding)
+ // return ((UnresolvedReferenceBinding) two).resolvedType == one;
+ return false; // all other type bindings are identical
+}
+boolean canSkipInheritedMethods() {
+ if (this.type.superclass() != null)
+ if (this.type.superclass().isAbstract() || this.type.superclass().isParameterizedType())
+ return false;
+ return this.type.superInterfaces() == NoSuperInterfaces;
+}
+boolean canSkipInheritedMethods(MethodBinding one, MethodBinding two) {
+ return two == null // already know one is not null
+ || (one.declaringClass == two.declaringClass && !one.declaringClass.isParameterizedType());
+}
+void checkForBridgeMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+ MethodBinding originalInherited = inheritedMethod.original();
+ if (inheritedMethod != originalInherited) {
+ MethodBinding[] toCheck = (MethodBinding[]) this.currentMethods.get(currentMethod.selector);
+ if (toCheck.length > 1) {
+ // must check to see if a bridge method will collide with another current method (see 77861)
+ for (int i = 0, length = toCheck.length; i < length; i++) {
+ if (currentMethod != toCheck[i] && toCheck[i].areParameterErasuresEqual(originalInherited)) {
+ problemReporter(toCheck[i]).methodNameClash(toCheck[i], originalInherited); // bridge method will collide
+ return;
+ }
+ }
+ }
+ }
+
+ // so the parameters are equal and the return type is compatible b/w the currentMethod & the substituted inheritedMethod
+ // then when do you need a bridge method?
+ if (originalInherited.returnType != currentMethod.returnType) {
+ switch (originalInherited.returnType.leafComponentType().kind()) {
+ case Binding.PARAMETERIZED_TYPE :
+ if (!currentMethod.returnType.leafComponentType().isParameterizedType())
+ problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, ((MethodDeclaration) currentMethod.sourceMethod()).returnType);
+ break;
+ case Binding.TYPE_PARAMETER :
+ if (!currentMethod.returnType.leafComponentType().isTypeVariable())
+ problemReporter(currentMethod).unsafeReturnTypeOverride(currentMethod, originalInherited, ((MethodDeclaration) currentMethod.sourceMethod()).returnType);
+ break;
+ }
+ }
+ this.type.addSyntheticBridgeMethod(originalInherited, currentMethod);
+}
+void checkInheritedMethods(MethodBinding[] methods, int length) {
+ int count = length;
+ nextMethod : for (int i = 0, l = length - 1; i < l;) {
+ MethodBinding method = methods[i++];
+ for (int j = i; j <= l; j++) {
+ if (method.declaringClass == methods[j].declaringClass && doesMethodOverride(method, methods[j])) {
+ // found an inherited ParameterizedType that defines duplicate methods
+ problemReporter().duplicateInheritedMethods(this.type, method, methods[j]);
+ count--;
+ methods[i - 1] = null;
+ continue nextMethod;
+ }
+ }
+ }
+ if (count < length) {
+ if (count == 1) return; // no need to continue since only 1 inherited method is left
+ MethodBinding[] newMethods = new MethodBinding[count];
+ for (int i = length; --i >= 0;)
+ if (methods[i] != null)
+ newMethods[--count] = methods[i];
+ methods = newMethods;
+ length = newMethods.length;
+ }
+
+ super.checkInheritedMethods(methods, length);
+}
+MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) {
+ if (inheritedMethod == null) return null;
+
+ // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved
+ // should we push these tests to where they're needed? returnType.isCompatibleWith && parameter isEquivalentTo ?
+ if (currentMethod.declaringClass instanceof BinaryTypeBinding)
+ ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod);
+ if (inheritedMethod.declaringClass instanceof BinaryTypeBinding)
+ ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod);
+
+ TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables();
+ if (inheritedTypeVariables == NoTypeVariables) return inheritedMethod;
+ TypeVariableBinding[] typeVariables = currentMethod == null ? NoTypeVariables : currentMethod.typeVariables;
+
+ int inheritedLength = inheritedTypeVariables.length;
+ int length = typeVariables.length;
+ TypeBinding[] arguments = new TypeBinding[inheritedLength];
+ if (inheritedLength <= length) {
+ System.arraycopy(typeVariables, 0, arguments, 0, inheritedLength);
+ } else {
+ System.arraycopy(typeVariables, 0, arguments, 0, length);
+ for (int i = length; i < inheritedLength; i++)
+ arguments[i] = inheritedTypeVariables[i].erasure();
+ }
+ ParameterizedGenericMethodBinding substitute =
+ new ParameterizedGenericMethodBinding(inheritedMethod, arguments, this.environment);
+ for (int i = 0; i < inheritedLength; i++)
+ if (!inheritedTypeVariables[i].boundCheck(substitute, arguments[i]))
+ return inheritedMethod; // incompatible due to bound check
+ return substitute;
+}
+boolean detectNameClash(MethodBinding one, MethodBinding substituteTwo, boolean checkParameters) {
+ if (doTypeVariablesClash(one, substituteTwo) || (checkParameters && doParametersClash(one, substituteTwo))) {
+ if (this.type == one.declaringClass)
+ problemReporter(one).methodNameClash(one, substituteTwo);
+ else
+ problemReporter().inheritedMethodsHaveNameClash(this.type, one, substituteTwo);
+ return true;
+ }
+ return false;
+}
+public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
+ return super.doesMethodOverride(method, computeSubstituteMethod(inheritedMethod, method));
+}
+boolean doParametersClash(MethodBinding one, MethodBinding substituteTwo) {
+ // must check each parameter pair to see if parameterized types are compatible
+ TypeBinding[] oneParams = one.parameters;
+ TypeBinding[] twoParams = substituteTwo.parameters;
+ for (int i = 0, l = oneParams.length; i < l; i++) {
+ if (oneParams[i] == twoParams[i]) continue;
+ if (!oneParams[i].leafComponentType().isParameterizedType()) continue;
+
+ if (!twoParams[i].leafComponentType().isParameterizedType()
+ || !oneParams[i].isEquivalentTo(twoParams[i])
+ || !twoParams[i].isEquivalentTo(oneParams[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
+ TypeBinding[] currentVars = one.typeVariables;
+ TypeBinding[] inheritedVars = substituteTwo.original().typeVariables;
+ return currentVars.length != inheritedVars.length
+ && currentVars.length > 0 && inheritedVars.length > 0; // must match unless all are replaced
+// && currentVars.length > 0;
+}
+boolean hasBoundedParameters(ParameterizedTypeBinding parameterizedType) {
+ TypeBinding[] arguments = parameterizedType.arguments;
+ if (arguments == null) return false;
+
+ nextArg : for (int i = 0, l = arguments.length; i < l; i++) {
+ if (arguments[i].isWildcard())
+ if (((WildcardBinding) arguments[i]).kind == org.eclipse.jdt.internal.compiler.ast.Wildcard.UNBOUND)
+ continue nextArg;
+ if (arguments[i].isTypeVariable())
+ if (((TypeVariableBinding) arguments[i]).firstBound == null)
+ continue nextArg;
+ return true;
+ }
+ return false;
+}
+boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
+ inheritedMethod = computeSubstituteMethod(inheritedMethod, existingMethod);
+ return inheritedMethod.returnType == existingMethod.returnType
+ && super.isInterfaceMethodImplemented(inheritedMethod, existingMethod, superType);
+}
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
index 8143f9b..2b78a5d 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
@@ -91,7 +91,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
if (synthLocal == null) return null;
if (synthLocal.matchingField == null)
- synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
+ synthLocal.matchingField = addSyntheticFieldForInnerclass(actualOuterLocalVariable);
return synthLocal;
}
@@ -103,7 +103,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
if (synthLocal == null) return null;
if (synthLocal.matchingField == null)
- synthLocal.matchingField = addSyntheticField(targetEnclosingType);
+ synthLocal.matchingField = addSyntheticFieldForInnerclass(targetEnclosingType);
return synthLocal;
}
@@ -209,7 +209,7 @@ public class NestedTypeBinding extends SourceTypeBinding {
if (!onlyExactMatch){
for (int i = enclosingInstances.length; --i >= 0;)
if (enclosingInstances[i].actualOuterLocalVariable == null)
- if (targetEnclosingType.isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
+ if (((ReferenceBinding)enclosingInstances[i].type).findSuperTypeErasingTo(targetEnclosingType) != null)
return enclosingInstances[i];
}
return null;
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index ee68a49..9f29f95 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -17,7 +17,7 @@ import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
public class PackageBinding extends Binding implements TypeConstants {
public char[][] compoundName;
PackageBinding parent;
- LookupEnvironment environment;
+ public LookupEnvironment environment;
HashtableOfType knownTypes;
HashtableOfPackage knownPackages;
protected PackageBinding() {
@@ -59,8 +59,15 @@ void addType(ReferenceBinding element) {
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
- return PACKAGE;
+public final int kind() {
+ return Binding.PACKAGE;
+}
+/*
+ * slash separated name
+ * org.eclipse.jdt.core --> org/eclipse/jdt/core
+ */
+public char[] computeUniqueKey() {
+ return CharOperation.concatWith(compoundName, '/');
}
private PackageBinding findPackage(char[] name) {
if (!environment.isPackage(this.compoundName, name))
@@ -112,22 +119,22 @@ PackageBinding getPackage0(char[] name) {
*/
ReferenceBinding getType(char[] name) {
- ReferenceBinding binding = getType0(name);
- if (binding == null) {
- if ((binding = environment.askForType(this, name)) == null) {
+ ReferenceBinding typeBinding = getType0(name);
+ if (typeBinding == null) {
+ if ((typeBinding = environment.askForType(this, name)) == null) {
// not found so remember a problem type binding in the cache for future lookups
addNotFoundType(name);
return null;
}
}
- if (binding == LookupEnvironment.TheNotFoundType)
+ if (typeBinding == LookupEnvironment.TheNotFoundType)
return null;
- if (binding instanceof UnresolvedReferenceBinding)
- binding = ((UnresolvedReferenceBinding) binding).resolve(environment);
- if (binding.isNestedType())
+
+ typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
+ if (typeBinding.isNestedType())
return new ProblemReferenceBinding(name, InternalNameProvided);
- return binding;
+ return typeBinding;
}
/* Answer the type named name if it exists in the cache.
* Answer theNotFoundType if it could not be resolved the first time
@@ -155,8 +162,7 @@ ReferenceBinding getType0(char[] name) {
public Binding getTypeOrPackage(char[] name) {
ReferenceBinding typeBinding = getType0(name);
if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) {
- if (typeBinding instanceof UnresolvedReferenceBinding)
- typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
+ typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
if (typeBinding.isNestedType())
return new ProblemReferenceBinding(name, InternalNameProvided);
return typeBinding;
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
new file mode 100644
index 0000000..d494449
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+
+/**
+ * Binding denoting a field after type substitution got performed.
+ * On parameterized type bindings, all fields got substituted, regardless whether
+ * their signature did involve generics or not, so as to get the proper declaringClass for
+ * these fields.
+ */
+public class ParameterizedFieldBinding extends FieldBinding {
+
+ public FieldBinding originalField;
+
+ public ParameterizedFieldBinding(ParameterizedTypeBinding parameterizedDeclaringClass, FieldBinding originalField) {
+ super (
+ originalField.name,
+ originalField.isStatic() ? originalField.type : parameterizedDeclaringClass.substitute(originalField.type),
+ originalField.modifiers,
+ parameterizedDeclaringClass,
+ null);
+ this.originalField = originalField;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
+ */
+ public Constant constant() {
+ return this.originalField.constant();
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#isConstantValue()
+ */
+ public boolean isConstantValue() {
+ return this.originalField.isConstantValue();
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.FieldBinding#original()
+ */
+ public FieldBinding original() {
+ return this.originalField.original();
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
+ */
+ public void setConstant(Constant constant) {
+ this.originalField.setConstant(constant);
+ }
+}
+
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
new file mode 100644
index 0000000..bf283be
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding denoting a generic method after type parameter substitutions got performed.
+ * On parameterized type bindings, all methods got substituted, regardless whether
+ * their signature did involve generics or not, so as to get the proper declaringClass for
+ * these methods.
+ */
+public class ParameterizedGenericMethodBinding extends ParameterizedMethodBinding implements Substitution {
+
+ public TypeBinding[] typeArguments;
+ private LookupEnvironment environment;
+ public boolean inferredReturnType;
+ public boolean wasInferred; // only set to true for instances resulting from method invocation inferrence
+ public boolean isRaw; // set to true for method behaving as raw for substitution purpose
+ public MethodBinding tiebreakMethod;
+
+ /**
+ * Create method of parameterized type, substituting original parameters with type arguments.
+ */
+ public ParameterizedGenericMethodBinding(MethodBinding originalMethod, TypeBinding[] typeArguments, LookupEnvironment environment) {
+
+ this.environment = environment;
+ this.modifiers = originalMethod.modifiers;
+ this.selector = originalMethod.selector;
+ this.declaringClass = originalMethod.declaringClass;
+ this.typeVariables = NoTypeVariables;
+ this.typeArguments = typeArguments;
+ this.isRaw = false;
+ this.originalMethod = originalMethod;
+ this.parameters = Scope.substitute(this, originalMethod.parameters);
+ this.thrownExceptions = Scope.substitute(this, originalMethod.thrownExceptions);
+ this.returnType = this.substitute(originalMethod.returnType);
+ this.wasInferred = true;// resulting from method invocation inferrence
+ }
+
+ /**
+ * Create raw generic method for raw type (double substitution from type vars with raw type arguments, and erasure of method variables)
+ * Only invoked for non-static generic methods of raw type
+ */
+ public ParameterizedGenericMethodBinding(MethodBinding originalMethod, RawTypeBinding rawType, LookupEnvironment environment) {
+
+ TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
+ int length = originalVariables.length;
+ TypeBinding[] rawArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ rawArguments[i] = originalVariables[i].erasure();
+ }
+ this.isRaw = true;
+ this.environment = environment;
+ this.modifiers = originalMethod.modifiers;
+ this.selector = originalMethod.selector;
+ this.declaringClass = rawType == null ? originalMethod.declaringClass : rawType;
+ this.typeVariables = NoTypeVariables;
+ this.typeArguments = rawArguments;
+ this.originalMethod = originalMethod;
+ boolean ignoreRawTypeSubstitution = rawType == null || originalMethod.isStatic();
+ this.parameters = Scope.substitute(this, ignoreRawTypeSubstitution
+ ? originalMethod.parameters // no substitution if original was static
+ : Scope.substitute(rawType, originalMethod.parameters));
+ this.thrownExceptions = Scope.substitute(this, ignoreRawTypeSubstitution
+ ? originalMethod.thrownExceptions // no substitution if original was static
+ : Scope.substitute(rawType, originalMethod.thrownExceptions));
+ this.returnType = this.substitute(ignoreRawTypeSubstitution
+ ? originalMethod.returnType // no substitution if original was static
+ : rawType.substitute(originalMethod.returnType));
+ this.wasInferred = false; // not resulting from method invocation inferrence
+ }
+
+ /**
+ * Perform inference of generic method type parameters and/or expected type
+ */
+ public static MethodBinding computeCompatibleMethod(MethodBinding originalMethod, TypeBinding[] arguments, Scope scope, InvocationSite invocationSite) {
+
+ ParameterizedGenericMethodBinding methodSubstitute;
+ TypeVariableBinding[] typeVariables = originalMethod.typeVariables;
+ TypeBinding[] substitutes = invocationSite.genericTypeArguments();
+
+ if (substitutes != null) {
+ if (substitutes.length != typeVariables.length) {
+ // incompatible due to wrong arity
+ return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes, TypeParameterArityMismatch);
+ }
+ methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, substitutes, scope.environment());
+ } else {
+ // perform type inference based on argument types and expected type
+
+ // collect substitutes by pattern matching parameters and arguments
+ TypeBinding[] parameters = originalMethod.parameters;
+ int varLength = typeVariables.length;
+ HashMap collectedSubstitutes = new HashMap(varLength);
+ for (int i = 0; i < varLength; i++)
+ collectedSubstitutes.put(typeVariables[i], new TypeBinding[1]);
+
+ // collect argument type mapping, handling varargs
+ if (originalMethod.isVarargs()) {
+ int paramLength = parameters.length;
+ int minArgLength = paramLength - 1;
+ int argLength = arguments.length;
+ // process mandatory arguments
+ for (int i = 0; i < minArgLength; i++)
+ parameters[i].collectSubstitutes(arguments[i], collectedSubstitutes);
+ // process optional arguments
+ if (minArgLength < argLength) {
+ TypeBinding varargType = parameters[minArgLength]; // last arg type - as is ?
+ if (paramLength != argLength // argument is passed as is ?
+ || (arguments[minArgLength] != NullBinding
+ && (arguments[minArgLength].dimensions() != varargType.dimensions()))) {
+ varargType = ((ArrayBinding)varargType).elementsType(); // eliminate one array dimension
+ }
+ for (int i = minArgLength; i < argLength; i++)
+ varargType.collectSubstitutes(arguments[i], collectedSubstitutes);
+ }
+ } else {
+ int paramLength = parameters.length;
+ for (int i = 0; i < paramLength; i++)
+ parameters[i].collectSubstitutes(arguments[i], collectedSubstitutes);
+ }
+ boolean needReturnTypeInference = false;
+ if (collectedSubstitutes.isEmpty()) {
+ // raw generic method inferred
+ methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, (RawTypeBinding)null, scope.environment());
+ } else {
+ substitutes = new TypeBinding[varLength];
+ for (int i = 0; i < varLength; i++) {
+ TypeBinding[] variableSubstitutes = (TypeBinding[]) collectedSubstitutes.get(typeVariables[i]);
+ TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(variableSubstitutes);
+ if (mostSpecificSubstitute == null)
+ return null; // incompatible
+ if (mostSpecificSubstitute == VoidBinding) {
+ needReturnTypeInference = true;
+ mostSpecificSubstitute = typeVariables[i];
+ }
+ substitutes[i] = mostSpecificSubstitute;
+ }
+ // apply inferred variable substitutions
+ methodSubstitute = new ParameterizedGenericMethodBinding(originalMethod, substitutes, scope.environment());
+ }
+
+ if (needReturnTypeInference && invocationSite instanceof MessageSend) {
+ MessageSend message = (MessageSend) invocationSite;
+ TypeBinding expectedType = message.expectedType;
+ if (expectedType == null) {
+ // 15.12.2.8 - if no expected type, then assume Object
+ // actually it rather seems to handle the returned variable case by expecting its erasure instead
+ if (methodSubstitute.returnType.isTypeVariable()) {
+ expectedType = methodSubstitute.returnType.erasure();
+ } else {
+ expectedType =scope.getJavaLangObject();
+ }
+ }
+ methodSubstitute.inferFromExpectedType(expectedType, scope);
+ }
+ }
+ // check bounds
+ if (!methodSubstitute.isRaw) {
+ for (int i = 0, length = typeVariables.length; i < length; i++) {
+ TypeVariableBinding typeVariable = typeVariables[i];
+ TypeBinding substitute = substitutes[i];
+ if (!typeVariable.boundCheck(methodSubstitute, substitute))
+ // incompatible due to bound check
+ return new ProblemMethodBinding(methodSubstitute, originalMethod.selector, new TypeBinding[]{substitutes[i], typeVariables[i] }, ParameterBoundMismatch);
+ }
+ }
+
+ return methodSubstitute;
+ }
+
+ /*
+ * parameterizedDeclaringUniqueKey dot selector originalMethodGenericSignature percent typeArguments
+ * p.X { void bar(T t, U u) { new X().bar(this, "") } } --> Lp/X;.bar(TT;TU;)V%
+ */
+ public char[] computeUniqueKey() {
+ if (this.isRaw)
+ return super.computeUniqueKey();
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(super.computeUniqueKey());
+ buffer.append('%');
+ buffer.append('<');
+ int length = this.typeArguments.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding typeArgument = this.typeArguments[i];
+ buffer.append(typeArgument.computeUniqueKey());
+ }
+ buffer.append('>');
+ int resultLength = buffer.length();
+ char[] result = new char[resultLength];
+ buffer.getChars(0, resultLength, result, 0);
+ return result;
+
+ }
+
+ /**
+ * Returns true if some parameters got substituted.
+ * NOTE: generic method invocation delegates to its declaring method (could be a parameterized one)
+ */
+ public boolean hasSubstitutedParameters() {
+ // generic parameterized method can represent either an invocation or a raw generic method
+ if (this.wasInferred)
+ return this.originalMethod.hasSubstitutedParameters();
+ return super.hasSubstitutedParameters();
+ }
+ /**
+ * Returns true if the return type got substituted.
+ * NOTE: generic method invocation delegates to its declaring method (could be a parameterized one)
+ */
+ public boolean hasSubstitutedReturnType() {
+ if (this.wasInferred)
+ return this.originalMethod.hasSubstitutedReturnType();
+ return super.hasSubstitutedReturnType();
+ }
+
+ public void inferFromExpectedType(TypeBinding expectedType, Scope scope) {
+ if (this.returnType == expectedType)
+ return;
+ if ((this.returnType.tagBits & TagBits.HasTypeVariable) == 0)
+ return;
+ Map substitutes = new HashMap(1);
+ int length = this.typeArguments.length;
+ TypeVariableBinding[] originalVariables = this.original().typeVariables;
+ boolean hasUnboundParameters = false;
+ for (int i = 0; i < length; i++) {
+ if (this.typeArguments[i] == originalVariables[i]) {
+ hasUnboundParameters = true;
+ substitutes.put(originalVariables[i], new TypeBinding[1]);
+ } else {
+ substitutes.put(originalVariables[i], new TypeBinding[] { this.typeArguments[i] });
+ }
+ }
+ if (!hasUnboundParameters)
+ return;
+ returnType.collectSubstitutes(expectedType, substitutes);
+ if (substitutes.isEmpty()) {
+ // raw generic method inferred
+ this.isRaw = true;
+ for (int i = 0; i < length; i++) {
+ this.typeArguments[i] = originalVariables[i].erasure();
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ TypeBinding[] variableSubstitutes = (TypeBinding[]) substitutes.get(originalVariables[i]);
+ TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(variableSubstitutes);
+ if (mostSpecificSubstitute == null) {
+ return; // TODO (philippe) should report no way to infer type
+ }
+ if (mostSpecificSubstitute == VoidBinding) {
+ // 15.12.2.8 - any remaining variable is assumed to be its erasure
+ mostSpecificSubstitute = originalVariables[i].erasure();
+ }
+ this.typeArguments[i] = mostSpecificSubstitute;
+ }
+ }
+ TypeBinding oldReturnType = this.returnType;
+ this.returnType = this.substitute(this.returnType);
+ this.inferredReturnType = this.returnType != oldReturnType;
+ this.parameters = Scope.substitute(this, this.parameters);
+ this.thrownExceptions = Scope.substitute(this, this.thrownExceptions);
+ }
+
+ /**
+ * Returns a type, where original type was substituted using the receiver
+ * parameterized method.
+ */
+ public TypeBinding substitute(TypeBinding originalType) {
+
+ switch (originalType.kind()) {
+
+ case Binding.TYPE_PARAMETER:
+ TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+ TypeVariableBinding[] variables = this.originalMethod.typeVariables;
+ int length = variables.length;
+ // check this variable can be substituted given parameterized type
+ if (originalVariable.rank < length && variables[originalVariable.rank] == originalVariable) {
+ return this.typeArguments[originalVariable.rank];
+ }
+ if (this.declaringClass instanceof Substitution) {
+ return ((Substitution)this.declaringClass).substitute(originalType);
+ }
+ break;
+
+ case Binding.PARAMETERIZED_TYPE:
+ ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+ ReferenceBinding originalEnclosing = originalType.enclosingType();
+ ReferenceBinding substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+ }
+ if (this.isRaw) {
+ return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);
+ }
+ TypeBinding[] originalArguments = originalParameterizedType.arguments;
+ TypeBinding[] substitutedArguments = originalArguments;
+ if (originalArguments != null) {
+ substitutedArguments = Scope.substitute(this, originalArguments);
+ }
+ if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+ identicalVariables: { // if substituted with original variables, then answer the generic type itself
+ if (substitutedEnclosing != originalEnclosing) break identicalVariables;
+ TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
+ length = originalVariables.length;
+ for (int i = 0; i < length; i++) {
+ if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
+ }
+ return originalParameterizedType.type;
+ }
+ return this.environment.createParameterizedType(
+ originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
+ }
+ break;
+
+ case Binding.ARRAY_TYPE:
+ TypeBinding originalLeafComponentType = originalType.leafComponentType();
+ TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+ if (substitute != originalLeafComponentType) {
+ return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+ }
+ break;
+
+ case Binding.WILDCARD_TYPE:
+ WildcardBinding wildcard = (WildcardBinding) originalType;
+ if (wildcard.kind != Wildcard.UNBOUND) {
+ TypeBinding originalBound = wildcard.bound;
+ TypeBinding substitutedBound = substitute(originalBound);
+ if (substitutedBound != originalBound) {
+ return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+ }
+ }
+ break;
+
+
+ case Binding.GENERIC_TYPE:
+ // treat as if parameterized with its type variables
+ ReferenceBinding originalGenericType = (ReferenceBinding) originalType;
+ originalEnclosing = originalType.enclosingType();
+ substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+ }
+ if (this.isRaw) {
+ return this.environment.createRawType(originalGenericType, substitutedEnclosing);
+ }
+ TypeVariableBinding[] originalVariables = originalGenericType.typeVariables();
+ length = originalVariables.length;
+ System.arraycopy(originalVariables, 0, originalArguments = new TypeBinding[length], 0, length);
+ substitutedArguments = Scope.substitute(this, originalArguments);
+ if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+ return this.environment.createParameterizedType(
+ originalGenericType, substitutedArguments, substitutedEnclosing);
+ }
+ break;
+ }
+ return originalType;
+ }
+ /**
+ * Returns the method to use during tiebreak (usually the method itself).
+ * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
+ */
+ public MethodBinding tiebreakMethod() {
+ if (this.tiebreakMethod == null) {
+ this.tiebreakMethod = new ParameterizedGenericMethodBinding(this.originalMethod, (RawTypeBinding)null, this.environment);
+ }
+ return this.tiebreakMethod;
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
new file mode 100644
index 0000000..bbe65e7
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding denoting a method after type parameter substitutions got performed.
+ * On parameterized type bindings, all methods got substituted, regardless whether
+ * their signature did involve generics or not, so as to get the proper declaringClass for
+ * these methods.
+ */
+public class ParameterizedMethodBinding extends MethodBinding {
+
+ protected MethodBinding originalMethod;
+
+ /**
+ * Create method of parameterized type, substituting original parameters/exception/return type with type arguments.
+ */
+ public ParameterizedMethodBinding(ParameterizedTypeBinding parameterizedDeclaringClass, MethodBinding originalMethod, boolean isStatic) {
+
+ super(
+ originalMethod.modifiers,
+ originalMethod.selector,
+ isStatic // no substitution if original was static
+ ? originalMethod.returnType
+ : parameterizedDeclaringClass.substitute(originalMethod.returnType),
+ isStatic // no substitution if original was static
+ ? originalMethod.parameters
+ : Scope.substitute(parameterizedDeclaringClass, originalMethod.parameters),
+ isStatic // no substitution if original was static
+ ? originalMethod.thrownExceptions
+ : Scope.substitute(parameterizedDeclaringClass, originalMethod.thrownExceptions),
+ parameterizedDeclaringClass);
+ this.originalMethod = originalMethod;
+ this.typeVariables = originalMethod.typeVariables;
+ }
+
+ public ParameterizedMethodBinding() {
+ // no init
+ }
+
+ /*
+ * parameterizedDeclaringUniqueKey dot selector originalMethodGenericSignature
+ * p.X { void bar(U u) { new X().bar("") } } --> Lp/X;.bar(TU;)V
+ */
+ public char[] computeUniqueKey() {
+ return computeUniqueKey(original());
+ }
+
+ /**
+ * The type of x.getClass() is substituted from 'Class extends Object>' into: 'Class extends |X|> where |X| is X's erasure.
+ */
+ public static ParameterizedMethodBinding instantiateGetClass(TypeBinding receiverType, MethodBinding originalMethod, Scope scope) {
+ ParameterizedMethodBinding method = new ParameterizedMethodBinding();
+ method.modifiers = originalMethod.modifiers;
+ method.selector = originalMethod.selector;
+ method.declaringClass = originalMethod.declaringClass;
+ method.typeVariables = NoTypeVariables;
+ method.originalMethod = originalMethod;
+ method.parameters = originalMethod.parameters;
+ method.thrownExceptions = originalMethod.thrownExceptions;
+ ReferenceBinding genericClassType = scope.getJavaLangClass();
+ method.returnType = scope.createParameterizedType(
+ genericClassType,
+ new TypeBinding[] { scope.environment().createWildcard(genericClassType, 0, receiverType.erasure(), Wildcard.EXTENDS) },
+ null);
+ return method;
+ }
+
+ /**
+ * Returns true if some parameters got substituted.
+ */
+ public boolean hasSubstitutedParameters() {
+ return this.parameters != originalMethod.parameters;
+ }
+
+ /**
+ * Returns true if the return type got substituted.
+ */
+ public boolean hasSubstitutedReturnType() {
+ return this.returnType != originalMethod.returnType;
+ }
+
+ /**
+ * Returns the original method (as opposed to parameterized instances)
+ */
+ public MethodBinding original() {
+ return this.originalMethod.original();
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
new file mode 100644
index 0000000..df77613
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -0,0 +1,856 @@
+/*******************************************************************************
+ * Copyright (c) 2000-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * A parameterized type encapsulates a type with type arguments,
+ */
+public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution {
+
+ public ReferenceBinding type;
+ public TypeBinding[] arguments;
+ public LookupEnvironment environment;
+ public char[] genericTypeSignature;
+ public ReferenceBinding superclass;
+ public ReferenceBinding[] superInterfaces;
+ public FieldBinding[] fields;
+ public ReferenceBinding[] memberTypes;
+ public MethodBinding[] methods;
+ private ReferenceBinding enclosingType;
+
+ public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment){
+
+ this.environment = environment;
+ initialize(type, arguments);
+ this.enclosingType = enclosingType; // never unresolved, never lazy per construction
+
+ if (type instanceof UnresolvedReferenceBinding)
+ ((UnresolvedReferenceBinding) type).addWrapper(this);
+ if (arguments != null) {
+ for (int i = 0, l = arguments.length; i < l; i++)
+ if (arguments[i] instanceof UnresolvedReferenceBinding)
+ ((UnresolvedReferenceBinding) arguments[i]).addWrapper(this);
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+ */
+ public boolean canBeInstantiated() {
+ return ((this.tagBits & HasDirectWildcard) == 0) // cannot instantiate param type with wildcard arguments
+ && super.canBeInstantiated();
+ }
+ public int kind() {
+ return PARAMETERIZED_TYPE;
+ }
+
+ /**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+ public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+ if (this.arguments == null) return;
+ if (otherType instanceof ReferenceBinding) {
+ // allow List to match with LinkedList
+ ReferenceBinding equivalent = this;
+ ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo((ReferenceBinding)this.type.erasure());
+ if (otherEquivalent == null) {
+ // allow LinkedList to match List (downcast scenario)
+ equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
+ if (equivalent == null) return;
+ otherEquivalent = (ReferenceBinding)otherType;
+ }
+ TypeBinding[] elements;
+ switch (equivalent.kind()) {
+ case Binding.GENERIC_TYPE :
+ elements = equivalent.typeVariables();
+ break;
+ case Binding.PARAMETERIZED_TYPE :
+ elements = ((ParameterizedTypeBinding)equivalent).arguments;
+ break;
+ default :
+ return;
+ }
+ TypeBinding[] otherElements;
+ switch (otherEquivalent.kind()) {
+ case Binding.GENERIC_TYPE :
+ otherElements = otherEquivalent.typeVariables();
+ break;
+ case Binding.PARAMETERIZED_TYPE :
+ otherElements = ((ParameterizedTypeBinding)otherEquivalent).arguments;
+ break;
+ case Binding.RAW_TYPE :
+ substitutes.clear(); // clear all variables to indicate raw generic method in the end
+ return;
+ default :
+ return;
+ }
+ for (int i = 0, length = elements.length; i < length; i++) {
+ elements[i].collectSubstitutes(otherElements[i], substitutes);
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#computeId()
+ */
+ public void computeId() {
+ this.id = NoId;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
+ */
+ public char[] constantPoolName() {
+ return this.type.constantPoolName(); // erasure
+ }
+
+ public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
+ return new ParameterizedMethodBinding(this, originalMethod, originalMethod.isStatic());
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+ */
+ public String debugName() {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(this.type.sourceName());
+ if (this.arguments != null) {
+ nameBuffer.append('<');
+ for (int i = 0, length = this.arguments.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(this.arguments[i].debugName());
+ }
+ nameBuffer.append('>');
+ }
+ return nameBuffer.toString();
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#enclosingType()
+ */
+ public ReferenceBinding enclosingType() {
+ if (this.isMemberType() && this.enclosingType == null) {
+ ReferenceBinding originalEnclosing = this.type.enclosingType();
+ this.enclosingType = originalEnclosing.isGenericType()
+ ? this.environment.createRawType(originalEnclosing, originalEnclosing.enclosingType()) // TODO (need to propagate in depth on enclosing type)
+ : originalEnclosing;
+ }
+ return this.enclosingType;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+ */
+ public TypeBinding erasure() {
+ return this.type.erasure(); // erasure
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fieldCount()
+ */
+ public int fieldCount() {
+ return this.type.fieldCount(); // same as erasure (lazy)
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#fields()
+ */
+ public FieldBinding[] fields() {
+ if (this.fields == null) {
+ try {
+ FieldBinding[] originalFields = this.type.fields();
+ int length = originalFields.length;
+ FieldBinding[] parameterizedFields = new FieldBinding[length];
+ for (int i = 0; i < length; i++)
+ // substitute all fields, so as to get updated declaring class at least
+ parameterizedFields[i] = new ParameterizedFieldBinding(this, originalFields[i]);
+ this.fields = parameterizedFields;
+ } finally {
+ // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
+ if (this.fields == null)
+ this.fields = NoFields;
+ }
+ }
+ return this.fields;
+ }
+
+ /**
+ * Ltype;
+ * LY;
+ */
+ public char[] genericTypeSignature() {
+ if (this.genericTypeSignature == null) {
+ StringBuffer sig = new StringBuffer(10);
+ if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
+ char[] typeSig = this.enclosingType().genericTypeSignature();
+ for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+ sig.append('.').append(this.sourceName());
+ } else {
+ char[] typeSig = this.type.signature();
+ for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+ }
+ if (this.arguments != null) {
+ sig.append('<');
+ for (int i = 0, length = this.arguments.length; i < length; i++) {
+ sig.append(this.arguments[i].genericTypeSignature());
+ }
+ sig.append('>'); //$NON-NLS-1$
+ }
+ sig.append(';');
+ int sigLength = sig.length();
+ this.genericTypeSignature = new char[sigLength];
+ sig.getChars(0, sigLength, this.genericTypeSignature, 0);
+ }
+ return this.genericTypeSignature;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactConstructor(TypeBinding[])
+ */
+ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
+ int argCount = argumentTypes.length;
+
+ if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
+ TypeBinding[] toMatch = method.parameters;
+ for (int p = 0; p < argCount; p++)
+ if (toMatch[p] != argumentTypes[p])
+ continue nextMethod;
+ return method;
+ }
+ }
+ } else {
+ MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
+ nextConstructor : for (int c = constructors.length; --c >= 0;) {
+ MethodBinding constructor = constructors[c];
+ TypeBinding[] toMatch = constructor.parameters;
+ if (toMatch.length == argCount) {
+ for (int p = 0; p < argCount; p++)
+ if (toMatch[p] != argumentTypes[p])
+ continue nextConstructor;
+ return constructor;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getExactMethod(char[], TypeBinding[])
+ */
+ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+ // sender from refScope calls recordTypeReference(this)
+ int argCount = argumentTypes.length;
+ int selectorLength = selector.length;
+ boolean foundNothing = true;
+ MethodBinding match = null;
+
+ if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+ foundNothing = false; // inner type lookups must know that a method with this name exists
+ if (method.parameters.length == argCount) {
+ TypeBinding[] toMatch = method.parameters;
+ for (int p = 0; p < argCount; p++)
+ if (toMatch[p] != argumentTypes[p])
+ continue nextMethod;
+ if (match != null) return null; // collision case
+ match = method;
+ }
+ }
+ }
+ } else {
+ MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
+ foundNothing = matchingMethods == NoMethods;
+ nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
+ MethodBinding method = matchingMethods[m];
+ TypeBinding[] toMatch = method.parameters;
+ if (toMatch.length == argCount) {
+ for (int p = 0; p < argCount; p++)
+ if (toMatch[p] != argumentTypes[p])
+ continue nextMethod;
+ if (match != null) return null; // collision case
+ match = method;
+ }
+ }
+ }
+ if (match != null) return match;
+
+ if (foundNothing) {
+ if (isInterface()) {
+ if (superInterfaces().length == 1) {
+ if (refScope != null)
+ refScope.recordTypeReference(superInterfaces[0]);
+ return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+ }
+ } else if (superclass() != null) {
+ if (refScope != null)
+ refScope.recordTypeReference(superclass);
+ return superclass.getExactMethod(selector, argumentTypes, refScope);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getField(char[], boolean)
+ */
+ public FieldBinding getField(char[] fieldName, boolean needResolve) {
+ fields(); // ensure fields have been initialized... must create all at once unlike methods
+ int fieldLength = fieldName.length;
+ for (int i = fields.length; --i >= 0;) {
+ FieldBinding field = fields[i];
+ if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName))
+ return field;
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMemberType(char[])
+ */
+ public ReferenceBinding getMemberType(char[] typeName) {
+ memberTypes(); // ensure memberTypes have been initialized... must create all at once unlike methods
+ int typeLength = typeName.length;
+ for (int i = this.memberTypes.length; --i >= 0;) {
+ ReferenceBinding memberType = this.memberTypes[i];
+ if (memberType.sourceName.length == typeLength && CharOperation.equals(memberType.sourceName, typeName))
+ return memberType;
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#getMethods(char[])
+ */
+ public MethodBinding[] getMethods(char[] selector) {
+ java.util.ArrayList matchingMethods = null;
+ if (this.methods != null) {
+ int selectorLength = selector.length;
+ for (int i = 0, length = this.methods.length; i < length; i++) {
+ MethodBinding method = this.methods[i];
+ if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+ if (matchingMethods == null)
+ matchingMethods = new java.util.ArrayList(2);
+ matchingMethods.add(method);
+ }
+ }
+ if (matchingMethods != null) {
+ MethodBinding[] result = new MethodBinding[matchingMethods.size()];
+ matchingMethods.toArray(result);
+ return result;
+ }
+ }
+ if ((modifiers & AccUnresolved) == 0) return NoMethods; // have created all the methods and there are no matches
+
+ MethodBinding[] parameterizedMethods = null;
+ try {
+ MethodBinding[] originalMethods = this.type.getMethods(selector);
+ int length = originalMethods.length;
+ if (length == 0) return NoMethods;
+
+ parameterizedMethods = new MethodBinding[length];
+ for (int i = 0; i < length; i++)
+ // substitute methods, so as to get updated declaring class at least
+ parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
+ if (this.methods == null) {
+ MethodBinding[] temp = new MethodBinding[length];
+ System.arraycopy(parameterizedMethods, 0, temp, 0, length);
+ this.methods = temp; // must be a copy of parameterizedMethods since it will be returned below
+ } else {
+ MethodBinding[] temp = new MethodBinding[length + this.methods.length];
+ System.arraycopy(parameterizedMethods, 0, temp, 0, length);
+ System.arraycopy(this.methods, 0, temp, length, this.methods.length);
+ this.methods = temp;
+ }
+ return parameterizedMethods;
+ } finally {
+ // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
+ if (parameterizedMethods == null)
+ this.methods = parameterizedMethods = NoMethods;
+ }
+ }
+ public boolean hasMemberTypes() {
+ return this.type.hasMemberTypes();
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#implementsMethod(MethodBinding)
+ */
+ public boolean implementsMethod(MethodBinding method) {
+ return this.type.implementsMethod(method); // erasure
+ }
+
+ void initialize(ReferenceBinding someType, TypeBinding[] someArguments) {
+ this.type = someType;
+ this.sourceName = someType.sourceName;
+ this.compoundName = someType.compoundName;
+ this.fPackage = someType.fPackage;
+ this.fileName = someType.fileName;
+ // should not be set yet
+ // this.superclass = null;
+ // this.superInterfaces = null;
+ // this.fields = null;
+ // this.methods = null;
+ this.modifiers = someType.modifiers | AccGenericSignature | AccUnresolved; // until methods() is sent
+ if (someArguments != null) {
+ this.arguments = someArguments;
+ for (int i = 0, length = someArguments.length; i < length; i++) {
+ TypeBinding someArgument = someArguments[i];
+ boolean isWildcardArgument = someArgument.isWildcard();
+ if (isWildcardArgument) {
+ this.tagBits |= HasDirectWildcard;
+ }
+ if (!isWildcardArgument || ((WildcardBinding) someArgument).kind != Wildcard.UNBOUND) {
+ this.tagBits |= IsBoundParameterizedType;
+ }
+ this.tagBits |= someArgument.tagBits & (HasTypeVariable);
+ }
+ }
+ this.tagBits |= someType.tagBits & (IsLocalType| IsMemberType | IsNestedType);
+ }
+
+ protected void initializeArguments() {
+ // do nothing for true parameterized types (only for raw types)
+ }
+
+ public boolean isEquivalentTo(TypeBinding otherType) {
+ if (this == otherType)
+ return true;
+ if (otherType == null)
+ return false;
+ switch(otherType.kind()) {
+
+ case Binding.WILDCARD_TYPE :
+ return ((WildcardBinding) otherType).boundCheck(this);
+
+ case Binding.PARAMETERIZED_TYPE :
+ if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
+ return false; // should have been identical
+ ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
+ if (this.type != otherParamType.type)
+ return false;
+ if (!isStatic()) { // static member types do not compare their enclosing
+ ReferenceBinding enclosing = enclosingType();
+ if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
+ return false;
+ }
+ int length = this.arguments == null ? 0 : this.arguments.length;
+ TypeBinding[] otherArguments = otherParamType.arguments;
+ int otherLength = otherArguments == null ? 0 : otherArguments.length;
+ if (otherLength != length)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
+ return false;
+ }
+ return true;
+
+ case Binding.RAW_TYPE :
+ return erasure() == otherType.erasure();
+ }
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#memberTypes()
+ */
+ public ReferenceBinding[] memberTypes() {
+ if (this.memberTypes == null) {
+ try {
+ ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
+ int length = originalMemberTypes.length;
+ ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
+ for (int i = 0; i < length; i++)
+ // substitute all member types, so as to get updated enclosing types
+ parameterizedMemberTypes[i] = this.environment.createParameterizedType(originalMemberTypes[i], null, this);
+ this.memberTypes = parameterizedMemberTypes;
+ } finally {
+ // if the original fields cannot be retrieved (ex. AbortCompilation), then assume we do not have any fields
+ if (this.memberTypes == null)
+ this.memberTypes = NoMemberTypes;
+ }
+ }
+ return this.memberTypes;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#methods()
+ */
+ public MethodBinding[] methods() {
+ if ((modifiers & AccUnresolved) == 0)
+ return this.methods;
+
+ try {
+ MethodBinding[] originalMethods = this.type.methods();
+ int length = originalMethods.length;
+ MethodBinding[] parameterizedMethods = new MethodBinding[length];
+ for (int i = 0; i < length; i++)
+ // substitute all methods, so as to get updated declaring class at least
+ parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
+ this.methods = parameterizedMethods;
+ } finally {
+ // if the original methods cannot be retrieved (ex. AbortCompilation), then assume we do not have any methods
+ if (this.methods == null)
+ this.methods = NoMethods;
+
+ modifiers &= ~AccUnresolved;
+ }
+ return this.methods;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedSourceName()
+ */
+ public char[] qualifiedSourceName() {
+ return this.type.qualifiedSourceName();
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+ */
+ public char[] readableName() {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ if (this.isMemberType()) {
+ nameBuffer.append(CharOperation.concat(this.enclosingType().readableName(), sourceName, '.'));
+ } else {
+ nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
+ }
+ if (this.arguments != null) {
+ nameBuffer.append('<');
+ for (int i = 0, length = this.arguments.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(this.arguments[i].readableName());
+ }
+ nameBuffer.append('>');
+ }
+ int nameLength = nameBuffer.length();
+ char[] readableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, readableName, 0);
+ return readableName;
+ }
+
+ ReferenceBinding resolve() {
+ // TODO need flag to know that this has already been done... should it be on ReferenceBinding?
+ ReferenceBinding resolvedType = BinaryTypeBinding.resolveType(this.type, this.environment, false); // still part of parameterized type ref
+ if (this.arguments != null) {
+ int argLength = this.arguments.length;
+ for (int i = 0; i < argLength; i++)
+ BinaryTypeBinding.resolveType(this.arguments[i], this.environment, this, i);
+ // arity check
+ TypeVariableBinding[] refTypeVariables = resolvedType.typeVariables();
+ if (refTypeVariables == NoTypeVariables) { // check generic
+ this.environment.problemReporter.nonGenericTypeCannotBeParameterized(null, resolvedType, this.arguments);
+ return this; // cannot reach here as AbortCompilation is thrown
+ } else if (argLength != refTypeVariables.length) { // check arity
+ this.environment.problemReporter.incorrectArityForParameterizedType(null, resolvedType, this.arguments);
+ return this; // cannot reach here as AbortCompilation is thrown
+ }
+ // check argument type compatibility
+ for (int i = 0; i < argLength; i++) {
+ TypeBinding resolvedArgument = this.arguments[i];
+ if (!refTypeVariables[i].boundCheck(this, resolvedArgument)) {
+ this.environment.problemReporter.typeMismatchError(resolvedArgument, refTypeVariables[i], resolvedType, null);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+ */
+ public char[] shortReadableName() {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ if (this.isMemberType()) {
+ nameBuffer.append(CharOperation.concat(this.enclosingType().shortReadableName(), sourceName, '.'));
+ } else {
+ nameBuffer.append(this.type.sourceName);
+ }
+ if (this.arguments != null) {
+ nameBuffer.append('<');
+ for (int i = 0, length = this.arguments.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(this.arguments[i].shortReadableName());
+ }
+ nameBuffer.append('>');
+ }
+ int nameLength = nameBuffer.length();
+ char[] shortReadableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, shortReadableName, 0);
+ return shortReadableName;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+ */
+ public char[] signature() {
+ if (this.signature == null) {
+ this.signature = this.type.signature(); // erasure
+ }
+ return this.signature;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#sourceName()
+ */
+ public char[] sourceName() {
+ return this.type.sourceName();
+ }
+
+ /**
+ * Returns a type, where original type was substituted using the receiver
+ * parameterized type.
+ */
+ public TypeBinding substitute(TypeBinding originalType) {
+
+ switch (originalType.kind()) {
+
+ case Binding.TYPE_PARAMETER:
+ TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+ ParameterizedTypeBinding currentType = this;
+ while (true) {
+ if (currentType.arguments != null) {
+ TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
+ int length = typeVariables.length;
+ // check this variable can be substituted given parameterized type
+ if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
+ return currentType.arguments[originalVariable.rank];
+ }
+ }
+ // recurse on enclosing type, as it may hold more substitutions to perform
+ ReferenceBinding enclosing = currentType.enclosingType();
+ if (!(enclosing instanceof ParameterizedTypeBinding))
+ break;
+ currentType = (ParameterizedTypeBinding) enclosing;
+ }
+ break;
+
+ case Binding.PARAMETERIZED_TYPE:
+ ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+ ReferenceBinding originalEnclosing = originalType.enclosingType();
+ ReferenceBinding substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+ }
+ TypeBinding[] originalArguments = originalParameterizedType.arguments;
+ TypeBinding[] substitutedArguments = originalArguments;
+ if (originalArguments != null) {
+ substitutedArguments = Scope.substitute(this, originalArguments);
+ }
+ if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+ identicalVariables: { // if substituted with original variables, then answer the generic type itself
+ if (substitutedEnclosing != originalEnclosing) break identicalVariables;
+ TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
+ for (int i = 0, length = originalVariables.length; i < length; i++) {
+ if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
+ }
+ return originalParameterizedType.type;
+ }
+ return this.environment.createParameterizedType(
+ originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
+ }
+ break;
+
+ case Binding.ARRAY_TYPE:
+ TypeBinding originalLeafComponentType = originalType.leafComponentType();
+ TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+ if (substitute != originalLeafComponentType) {
+ return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+ }
+ break;
+
+ case Binding.WILDCARD_TYPE:
+ WildcardBinding wildcard = (WildcardBinding) originalType;
+ if (wildcard.kind != Wildcard.UNBOUND) {
+ TypeBinding originalBound = wildcard.bound;
+ TypeBinding substitutedBound = substitute(originalBound);
+ if (substitutedBound != originalBound) {
+ return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+ }
+ }
+ break;
+
+ case Binding.GENERIC_TYPE:
+ // treat as if parameterized with its type variables
+ ReferenceBinding originalGenericType = (ReferenceBinding) originalType;
+ originalEnclosing = originalType.enclosingType();
+ substitutedEnclosing = originalEnclosing;
+ if (originalEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(originalEnclosing);
+ }
+ TypeVariableBinding[] originalVariables = originalGenericType.typeVariables();
+ int length = originalVariables.length;
+ System.arraycopy(originalVariables, 0, originalArguments = new TypeBinding[length], 0, length);
+ substitutedArguments = Scope.substitute(this, originalArguments);
+ if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+ return this.environment.createParameterizedType(
+ originalGenericType, substitutedArguments, substitutedEnclosing);
+ }
+ break;
+ }
+ return originalType;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superclass()
+ */
+ public ReferenceBinding superclass() {
+ if (this.superclass == null) {
+ // note: Object cannot be generic
+ ReferenceBinding genericSuperclass = this.type.superclass();
+ if (genericSuperclass == null) return null; // e.g. interfaces
+ this.superclass = (ReferenceBinding) substitute(genericSuperclass);
+ }
+ return this.superclass;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
+ */
+ public ReferenceBinding[] superInterfaces() {
+ if (this.superInterfaces == null) {
+ this.superInterfaces = Scope.substitute(this, this.type.superInterfaces());
+ }
+ return this.superInterfaces;
+ }
+
+ public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+ boolean update = false;
+ if (this.type == unresolvedType) {
+ this.type = resolvedType; // cannot be raw since being parameterized below
+ update = true;
+ }
+ if (this.arguments != null) {
+ for (int i = 0, l = this.arguments.length; i < l; i++) {
+ if (this.arguments[i] == unresolvedType) {
+ this.arguments[i] = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+ update = true;
+ }
+ }
+ }
+ if (update)
+ initialize(this.type, this.arguments);
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticEnclosingInstanceTypes()
+ */
+ public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
+ return this.type.syntheticEnclosingInstanceTypes();
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#syntheticOuterLocalVariables()
+ */
+ public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+ return this.type.syntheticOuterLocalVariables();
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#qualifiedPackageName()
+ */
+ public char[] qualifiedPackageName() {
+ return this.type.qualifiedPackageName();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(30);
+ if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
+ if (isPublic()) buffer.append("public "); //$NON-NLS-1$
+ if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
+ if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
+ if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
+ if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
+ if (isFinal()) buffer.append("final "); //$NON-NLS-1$
+
+ buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(this.debugName());
+
+ buffer.append("\n\textends "); //$NON-NLS-1$
+ buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
+
+ if (superInterfaces != null) {
+ if (superInterfaces != NoSuperInterfaces) {
+ buffer.append("\n\timplements : "); //$NON-NLS-1$
+ for (int i = 0, length = superInterfaces.length; i < length; i++) {
+ if (i > 0)
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
+ }
+ }
+ } else {
+ buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
+ }
+
+ if (enclosingType() != null) {
+ buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
+ buffer.append(enclosingType().debugName());
+ }
+
+ if (fields != null) {
+ if (fields != NoFields) {
+ buffer.append("\n/* fields */"); //$NON-NLS-1$
+ for (int i = 0, length = fields.length; i < length; i++)
+ buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
+ }
+ } else {
+ buffer.append("NULL FIELDS"); //$NON-NLS-1$
+ }
+
+ if (methods != null) {
+ if (methods != NoMethods) {
+ buffer.append("\n/* methods */"); //$NON-NLS-1$
+ for (int i = 0, length = methods.length; i < length; i++)
+ buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ } else {
+ buffer.append("NULL METHODS"); //$NON-NLS-1$
+ }
+
+// if (memberTypes != null) {
+// if (memberTypes != NoMemberTypes) {
+// buffer.append("\n/* members */"); //$NON-NLS-1$
+// for (int i = 0, length = memberTypes.length; i < length; i++)
+// buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+// } else {
+// buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
+// }
+
+ buffer.append("\n\n"); //$NON-NLS-1$
+ return buffer.toString();
+
+ }
+ public TypeVariableBinding[] typeVariables() {
+ if (this.arguments == null) {
+ // retain original type variables if not substituted (member type of parameterized type)
+ return this.type.typeVariables();
+ }
+ return NoTypeVariables;
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
index c4fab5f..b1dd4db 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
@@ -38,7 +38,7 @@ ProblemBinding(char[] name, ReferenceBinding searchType, int problemId) {
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
+public final int kind() {
return VARIABLE | TYPE;
}
/* API
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
index 71f0547..e5ae8db 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
@@ -11,21 +11,23 @@
package org.eclipse.jdt.internal.compiler.lookup;
public class ProblemMethodBinding extends MethodBinding {
- private int problemId;
- public MethodBinding closestMatch;
-public ProblemMethodBinding(char[] selector, TypeBinding[] args, int problemId) {
+
+ private int problemReason;
+ public MethodBinding closestMatch; // TODO (philippe) should rename into #alternateMatch
+
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, int problemReason) {
this.selector = selector;
this.parameters = (args == null || args.length == 0) ? NoParameters : args;
- this.problemId = problemId;
+ this.problemReason = problemReason;
}
-public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemId) {
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemReason) {
this.selector = selector;
this.parameters = (args == null || args.length == 0) ? NoParameters : args;
this.declaringClass = declaringClass;
- this.problemId = problemId;
+ this.problemReason = problemReason;
}
-public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemId) {
- this(selector, args, problemId);
+public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemReason) {
+ this(selector, args, problemReason);
this.closestMatch = closestMatch;
if (closestMatch != null) this.declaringClass = closestMatch.declaringClass;
}
@@ -35,6 +37,6 @@ public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBin
*/
public final int problemId() {
- return problemId;
+ return this.problemReason;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
index b34f200..97570b7 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
@@ -20,4 +20,10 @@ public interface ProblemReasons {
final int NonStaticReferenceInConstructorInvocation = 6;
final int NonStaticReferenceInStaticContext = 7;
final int ReceiverTypeNotVisible = 8;
+ final int IllegalSuperTypeVariable = 9;
+ final int ParameterBoundMismatch = 10; // for generic method
+ final int TypeParameterArityMismatch = 11; // for generic method
+ final int ParameterizedMethodTypeMismatch = 12; // for generic method
+ final int TypeArgumentsForRawGenericMethod = 13; // for generic method
+ final int InvalidTypeForStaticImport = 14;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index 7225ba7..00d8a18 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -12,31 +12,32 @@ package org.eclipse.jdt.internal.compiler.lookup;
public class ProblemReferenceBinding extends ReferenceBinding {
public ReferenceBinding original;
- private int problemId;
+ private int problemReason;
+ public ReferenceBinding alternateMatch;
+
// NOTE: must only answer the subset of the name related to the problem
-public ProblemReferenceBinding(char[][] compoundName, int problemId) {
- this(compoundName, null, problemId);
+public ProblemReferenceBinding(char[][] compoundName, int problemReason) {
+ this(compoundName, null, problemReason);
}
-public ProblemReferenceBinding(char[] name, int problemId) {
- this(new char[][] {name}, null, problemId);
+public ProblemReferenceBinding(char[] name, int problemReason) {
+ this(new char[][] {name}, null, problemReason);
}
-public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemId) {
+public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemReason) {
this.compoundName = compoundName;
this.original = original;
- this.problemId = problemId;
+ this.problemReason = problemReason;
}
-public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemId) {
- this(new char[][] {name}, original, problemId);
+public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemReason) {
+ this(new char[][] {name}, original, problemReason);
}
/* API
* Answer the problem id associated with the receiver.
* NoError if the receiver is a valid binding.
*/
-
-public final int problemId() {
- return problemId;
+public int problemId() {
+ return this.problemReason;
}
/**
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
new file mode 100644
index 0000000..ce950e2
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Denote a raw type, i.e. a generic type referenced without any type arguments.
+ * e.g. X can be used a raw type 'X', in which case it
+ * will behave as X
+ */
+public class RawTypeBinding extends ParameterizedTypeBinding {
+
+ /**
+ * Raw type arguments are erasure of respective parameter bounds. But we may not have resolved
+ * these bounds yet if creating raw types while supertype hierarchies are being connected.
+ * Therefore, use 'null' instead, and access these in a lazy way later on (when substituting).
+ */
+ public RawTypeBinding(ReferenceBinding type, ReferenceBinding enclosingType, LookupEnvironment environment){
+ super(type, null, enclosingType, environment);
+ if (enclosingType == null || (enclosingType.modifiers & AccGenericSignature) == 0)
+ this.modifiers &= ~AccGenericSignature; // only need signature if enclosing needs one
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding)
+ */
+ public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
+ if (originalMethod.typeVariables == NoTypeVariables || originalMethod.isStatic()) {
+ return super.createParameterizedMethod(originalMethod);
+ }
+ return new ParameterizedGenericMethodBinding(originalMethod, this, this.environment);
+ }
+
+ public int kind() {
+ return RAW_TYPE;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+ */
+ public String debugName() {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(this.type.sourceName()).append("#RAW"); //$NON-NLS-1$
+ return nameBuffer.toString();
+ }
+
+ /**
+ * Ltype;
+ * LY;
+ */
+ public char[] genericTypeSignature() {
+
+ if (this.genericTypeSignature == null) {
+ StringBuffer sig = new StringBuffer(10);
+ if (this.isMemberType() && this.enclosingType().isParameterizedType()) {
+ char[] typeSig = this.enclosingType().genericTypeSignature();
+ for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
+ sig.append('.').append(this.sourceName()).append(';');
+ int sigLength = sig.length();
+ this.genericTypeSignature = new char[sigLength];
+ sig.getChars(0, sigLength, this.genericTypeSignature, 0);
+ } else {
+ this.genericTypeSignature = this.type.signature(); // erasure
+ }
+ }
+ return this.genericTypeSignature;
+ }
+
+ public boolean isEquivalentTo(TypeBinding otherType) {
+ if (this == otherType) return true;
+ if (otherType == null) return false;
+ if (otherType.isWildcard()) // wildcard
+ return ((WildcardBinding) otherType).boundCheck(this);
+ return otherType.erasure() == this.erasure();
+ }
+ /**
+ * Raw type is not treated as a standard parameterized type
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#isParameterizedType()
+ */
+ public boolean isParameterizedType() {
+ return false;
+ }
+ public boolean isRawType() {
+ return true;
+ }
+
+ protected void initializeArguments() {
+ TypeVariableBinding[] typeVariables = this.type.typeVariables();
+ int length = typeVariables.length;
+ TypeBinding[] typeArguments = new TypeBinding[length];
+ for (int i = 0; i < length; i++) {
+ typeArguments[i] = typeVariables[i].erasure();
+ }
+ this.arguments = typeArguments;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+ */
+ public char[] readableName() /*java.lang.Object, p.X */ {
+ char[] readableName;
+ if (isMemberType()) {
+ readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+ } else {
+ readableName = CharOperation.concatWith(this.type.compoundName, '.');
+ }
+ return readableName;
+ }
+
+ /**
+ * Returns a type, where original type was substituted using the receiver
+ * raw type.
+ * On raw types, all parameterized type denoting same original type are converted
+ * to raw types. e.g.
+ * class X {
+ * X foo;
+ * X bar;
+ * } when used in raw fashion, then type of both foo and bar is raw type X.
+ */
+ public TypeBinding substitute(TypeBinding originalType) {
+
+ switch (originalType.kind()) {
+
+ case Binding.TYPE_PARAMETER:
+ TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
+ ParameterizedTypeBinding currentType = this;
+ while (true) {
+ TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
+ int length = typeVariables.length;
+ // check this variable can be substituted given parameterized type
+ if (originalVariable.rank < length && typeVariables[originalVariable.rank] == originalVariable) {
+ // lazy init, since cannot do so during binding creation if during supertype connection
+ if (currentType.arguments == null) currentType.initializeArguments();
+ if (currentType.arguments != null)
+ return currentType.arguments[originalVariable.rank];
+ }
+ // recurse on enclosing type, as it may hold more substitutions to perform
+ ReferenceBinding enclosing = currentType.enclosingType();
+ if (!(enclosing instanceof ParameterizedTypeBinding))
+ break;
+ currentType = (ParameterizedTypeBinding) enclosing;
+ }
+ break;
+
+ case Binding.PARAMETERIZED_TYPE:
+ ReferenceBinding substitutedEnclosing = originalType.enclosingType();
+ if (substitutedEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+ }
+ ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
+ return this.environment.createRawType(originalParameterizedType.type, substitutedEnclosing);
+
+ case Binding.GENERIC_TYPE:
+ substitutedEnclosing = originalType.enclosingType();
+ if (substitutedEnclosing != null) {
+ substitutedEnclosing = (ReferenceBinding) this.substitute(substitutedEnclosing);
+ }
+ return this.environment.createRawType((ReferenceBinding)originalType, substitutedEnclosing);
+
+ case Binding.WILDCARD_TYPE:
+ WildcardBinding wildcard = (WildcardBinding) originalType;
+ if (wildcard.kind != Wildcard.UNBOUND) {
+ TypeBinding originalBound = wildcard.bound;
+ TypeBinding substitutedBound = substitute(originalBound);
+ if (substitutedBound != originalBound) {
+ return this.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, wildcard.kind);
+ }
+ }
+ break;
+
+ case Binding.ARRAY_TYPE:
+ TypeBinding originalLeafComponentType = originalType.leafComponentType();
+ TypeBinding substitute = substitute(originalLeafComponentType); // substitute could itself be array type
+ if (substitute != originalLeafComponentType) {
+ return this.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+ }
+ break;
+ }
+ return originalType;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+ */
+ public char[] shortReadableName() /*Object*/ {
+ char[] shortReadableName;
+ if (isMemberType()) {
+ shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+ } else {
+ shortReadableName = this.type.sourceName;
+ }
+ return shortReadableName;
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 6cda282..e7f50f5 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -45,7 +45,7 @@ public MethodBinding[] availableMethods() {
*/
public boolean canBeInstantiated() {
- return !(isAbstract() || isInterface());
+ return (this.modifiers & (AccAbstract | AccInterface | AccEnum | AccAnnotation)) == 0;
}
/* Answer true if the receiver is visible to the invocationPackage.
*/
@@ -91,7 +91,19 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBindin
if (isPrivate()) {
// answer true if the receiverType is the receiver or its enclosingType
// AND the invocationType and the receiver have a common enclosingType
- if (!(receiverType == this || receiverType == enclosingType())) return false;
+ receiverCheck: {
+ if (!(receiverType == this || receiverType == enclosingType())) {
+ // special tolerance for type variable direct bounds
+ if (receiverType.isTypeVariable()) {
+ TypeVariableBinding typeVariable = (TypeVariableBinding) receiverType;
+ if (typeVariable.isErasureBoundTo(this.erasure()) || typeVariable.isErasureBoundTo(enclosingType().erasure())) {
+ break receiverCheck;
+ }
+ }
+ return false;
+ }
+ }
+
if (invocationType != this) {
ReferenceBinding outerInvocationType = invocationType;
@@ -101,7 +113,7 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBindin
temp = temp.enclosingType();
}
- ReferenceBinding outerDeclaringClass = this;
+ ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
temp = outerDeclaringClass.enclosingType();
while (temp != null) {
outerDeclaringClass = temp;
@@ -168,7 +180,7 @@ public final boolean canBeSeenBy(Scope scope) {
temp = temp.enclosingType();
}
- ReferenceBinding outerDeclaringClass = this;
+ ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.erasure();
temp = outerDeclaringClass.enclosingType();
while (temp != null) {
outerDeclaringClass = temp;
@@ -181,96 +193,157 @@ public final boolean canBeSeenBy(Scope scope) {
return invocationType.fPackage == fPackage;
}
public void computeId() {
- if (compoundName.length != 3) {
- if (compoundName.length == 4 && CharOperation.equals(JAVA_LANG_REFLECT_CONSTRUCTOR, compoundName))
- id = T_JavaLangReflectConstructor;
- return;
- }
-
- if (!CharOperation.equals(JAVA, compoundName[0]))
- return;
-
- // remaining types MUST be in java.*.*
- if (!CharOperation.equals(LANG, compoundName[1])) {
- if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName))
- id = T_JavaIoPrintStream;
- else if (CharOperation.equals(JAVA_IO_SERIALIZABLE, compoundName))
- id = T_JavaIoSerializable;
- return;
- }
+
+ switch (compoundName.length) {
- // remaining types MUST be in java.lang.*
- char[] typeName = compoundName[2];
- if (typeName.length == 0) return; // just to be safe
- switch (typeName[0]) {
- case 'A' :
- if (CharOperation.equals(typeName, JAVA_LANG_ASSERTIONERROR[2]))
- id = T_JavaLangAssertionError;
- return;
- case 'B' :
- if (CharOperation.equals(typeName, JAVA_LANG_BOOLEAN[2]))
- id = T_JavaLangBoolean;
- else if (CharOperation.equals(typeName, JAVA_LANG_BYTE[2]))
- id = T_JavaLangByte;
- return;
- case 'C' :
- if (CharOperation.equals(typeName, JAVA_LANG_CHARACTER[2]))
- id = T_JavaLangCharacter;
- else if (CharOperation.equals(typeName, JAVA_LANG_CLASS[2]))
- id = T_JavaLangClass;
- else if (CharOperation.equals(typeName, JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2]))
- id = T_JavaLangClassNotFoundException;
- else if (CharOperation.equals(typeName, JAVA_LANG_CLONEABLE[2]))
- id = T_JavaLangCloneable;
- return;
- case 'D' :
- if (CharOperation.equals(typeName, JAVA_LANG_DOUBLE[2]))
- id = T_JavaLangDouble;
- return;
- case 'E' :
- if (CharOperation.equals(typeName, JAVA_LANG_ERROR[2]))
- id = T_JavaLangError;
- else if (CharOperation.equals(typeName, JAVA_LANG_EXCEPTION[2]))
- id = T_JavaLangException;
- return;
- case 'F' :
- if (CharOperation.equals(typeName, JAVA_LANG_FLOAT[2]))
- id = T_JavaLangFloat;
- return;
- case 'I' :
- if (CharOperation.equals(typeName, JAVA_LANG_INTEGER[2]))
- id = T_JavaLangInteger;
- return;
- case 'L' :
- if (CharOperation.equals(typeName, JAVA_LANG_LONG[2]))
- id = T_JavaLangLong;
- return;
- case 'N' :
- if (CharOperation.equals(typeName, JAVA_LANG_NOCLASSDEFERROR[2]))
- id = T_JavaLangNoClassDefError;
- return;
- case 'O' :
- if (CharOperation.equals(typeName, JAVA_LANG_OBJECT[2]))
- id = T_JavaLangObject;
- return;
- case 'S' :
- if (CharOperation.equals(typeName, JAVA_LANG_STRING[2]))
- id = T_JavaLangString;
- else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUFFER[2]))
- id = T_JavaLangStringBuffer;
- else if (CharOperation.equals(typeName, JAVA_LANG_SYSTEM[2]))
- id = T_JavaLangSystem;
- else if (CharOperation.equals(typeName, JAVA_LANG_SHORT[2]))
- id = T_JavaLangShort;
- return;
- case 'T' :
- if (CharOperation.equals(typeName, JAVA_LANG_THROWABLE[2]))
- id = T_JavaLangThrowable;
- return;
- case 'V' :
- if (CharOperation.equals(typeName, JAVA_LANG_VOID[2]))
- id = T_JavaLangVoid;
- return;
+ case 3 :
+ if (!CharOperation.equals(JAVA, compoundName[0]))
+ return;
+
+ // remaining types MUST be in java.*.*
+ if (!CharOperation.equals(LANG, compoundName[1])) {
+ if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName))
+ id = T_JavaIoPrintStream;
+ else if (CharOperation.equals(JAVA_UTIL_ITERATOR, compoundName))
+ id = T_JavaUtilIterator;
+ else if (CharOperation.equals(JAVA_IO_SERIALIZABLE, compoundName))
+ id = T_JavaIoSerializable;
+ return;
+ }
+
+ // remaining types MUST be in java.lang.*
+ char[] typeName = compoundName[2];
+ if (typeName.length == 0) return; // just to be safe
+ switch (typeName[0]) {
+ case 'A' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ASSERTIONERROR[2]))
+ id = T_JavaLangAssertionError;
+ return;
+ case 'B' :
+ if (CharOperation.equals(typeName, JAVA_LANG_BOOLEAN[2]))
+ id = T_JavaLangBoolean;
+ else if (CharOperation.equals(typeName, JAVA_LANG_BYTE[2]))
+ id = T_JavaLangByte;
+ return;
+ case 'C' :
+ if (CharOperation.equals(typeName, JAVA_LANG_CHARACTER[2]))
+ id = T_JavaLangCharacter;
+ else if (CharOperation.equals(typeName, JAVA_LANG_CLASS[2]))
+ id = T_JavaLangClass;
+ else if (CharOperation.equals(typeName, JAVA_LANG_CLASSNOTFOUNDEXCEPTION[2]))
+ id = T_JavaLangClassNotFoundException;
+ else if (CharOperation.equals(typeName, JAVA_LANG_CLONEABLE[2]))
+ id = T_JavaLangCloneable;
+ return;
+ case 'D' :
+ if (CharOperation.equals(typeName, JAVA_LANG_DOUBLE[2]))
+ id = T_JavaLangDouble;
+ else if (CharOperation.equals(typeName, JAVA_LANG_DEPRECATED[2]))
+ id = T_JavaLangDeprecated;
+ return;
+ case 'E' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ERROR[2]))
+ id = T_JavaLangError;
+ else if (CharOperation.equals(typeName, JAVA_LANG_EXCEPTION[2]))
+ id = T_JavaLangException;
+ else if (CharOperation.equals(typeName, JAVA_LANG_ENUM[2]))
+ id = T_JavaLangEnum;
+ return;
+ case 'F' :
+ if (CharOperation.equals(typeName, JAVA_LANG_FLOAT[2]))
+ id = T_JavaLangFloat;
+ return;
+ case 'I' :
+ if (CharOperation.equals(typeName, JAVA_LANG_INTEGER[2]))
+ id = T_JavaLangInteger;
+ else if (CharOperation.equals(typeName, JAVA_LANG_ITERABLE[2]))
+ id = T_JavaLangIterable;
+ else if (CharOperation.equals(typeName, JAVA_LANG_ILLEGALARGUMENTEXCEPTION[2]))
+ id = T_JavaLangIllegalArgumentException;
+ return;
+ case 'L' :
+ if (CharOperation.equals(typeName, JAVA_LANG_LONG[2]))
+ id = T_JavaLangLong;
+ return;
+ case 'N' :
+ if (CharOperation.equals(typeName, JAVA_LANG_NOCLASSDEFERROR[2]))
+ id = T_JavaLangNoClassDefError;
+ return;
+ case 'O' :
+ if (CharOperation.equals(typeName, JAVA_LANG_OBJECT[2]))
+ id = T_JavaLangObject;
+ else if (CharOperation.equals(typeName, JAVA_LANG_OVERRIDE[2]))
+ id = T_JavaLangOverride;
+ return;
+ case 'S' :
+ if (CharOperation.equals(typeName, JAVA_LANG_STRING[2]))
+ id = T_JavaLangString;
+ else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUFFER[2]))
+ id = T_JavaLangStringBuffer;
+ else if (CharOperation.equals(typeName, JAVA_LANG_STRINGBUILDER[2]))
+ id = T_JavaLangStringBuilder;
+ else if (CharOperation.equals(typeName, JAVA_LANG_SYSTEM[2]))
+ id = T_JavaLangSystem;
+ else if (CharOperation.equals(typeName, JAVA_LANG_SHORT[2]))
+ id = T_JavaLangShort;
+ else if (CharOperation.equals(typeName, JAVA_LANG_SUPPRESSWARNINGS[2]))
+ id = T_JavaLangSuppressWarnings;
+ return;
+ case 'T' :
+ if (CharOperation.equals(typeName, JAVA_LANG_THROWABLE[2]))
+ id = T_JavaLangThrowable;
+ return;
+ case 'V' :
+ if (CharOperation.equals(typeName, JAVA_LANG_VOID[2]))
+ id = T_JavaLangVoid;
+ return;
+ }
+ break;
+
+ case 4:
+ if (!CharOperation.equals(JAVA, compoundName[0]))
+ return;
+ if (!CharOperation.equals(LANG, compoundName[1]))
+ return;
+ char[] packageName = compoundName[2];
+ if (packageName.length == 0) return; // just to be safe
+ typeName = compoundName[3];
+ if (typeName.length == 0) return; // just to be safe
+ if (CharOperation.equals(packageName, REFLECT)) {
+ if (CharOperation.equals(typeName, JAVA_LANG_REFLECT_CONSTRUCTOR[3]))
+ id = T_JavaLangReflectConstructor;
+ return;
+ } else if (CharOperation.equals(packageName, ANNOTATION)) {
+ switch (typeName[0]) {
+ case 'A' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_ANNOTATION[3]))
+ id = T_JavaLangAnnotationAnnotation;
+ return;
+ case 'D' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_DOCUMENTED[3]))
+ id = T_JavaLangAnnotationDocumented;
+ return;
+ case 'E' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_ELEMENTTYPE[3]))
+ id = T_JavaLangAnnotationElementType;
+ return;
+ case 'I' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_INHERITED[3]))
+ id = T_JavaLangAnnotationInherited;
+ return;
+ case 'R' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_RETENTION[3]))
+ id = T_JavaLangAnnotationRetention;
+ else if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_RETENTIONPOLICY[3]))
+ id = T_JavaLangAnnotationRetentionPolicy;
+ return;
+ case 'T' :
+ if (CharOperation.equals(typeName, JAVA_LANG_ANNOTATION_TARGET[3]))
+ id = T_JavaLangAnnotationTarget;
+ return;
+ }
+ }
+ break;
}
}
/* Answer the receiver's constant pool name.
@@ -282,7 +355,7 @@ public char[] constantPoolName() /* java/lang/Object */ {
if (constantPoolName != null) return constantPoolName;
return constantPoolName = CharOperation.concatWith(compoundName, '/');
}
-String debugName() {
+public String debugName() {
return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
}
public final int depth() {
@@ -292,12 +365,6 @@ public final int depth() {
depth++;
return depth;
}
-/* Answer the receiver's enclosing type... null if the receiver is a top level type.
-*/
-
-public ReferenceBinding enclosingType() {
- return null;
-}
public final ReferenceBinding enclosingTypeAt(int relativeDepth) {
ReferenceBinding current = this;
while (relativeDepth-- > 0 && current != null)
@@ -310,6 +377,92 @@ public int fieldCount() {
public FieldBinding[] fields() {
return NoFields;
}
+/**
+ * Find supertype which erases to a given well-known type, or null if not found
+ * (using id avoids triggering the load of well-known type: 73740)
+ * NOTE: only works for erasures of well-known types, as random other types may share
+ * same id though being distincts.
+ *
+ */
+public ReferenceBinding findSuperTypeErasingTo(int erasureId, boolean erasureIsClass) {
+
+ if (erasure().id == erasureId) return this;
+ ReferenceBinding currentType = this;
+ // iterate superclass to avoid recording interfaces if searched supertype is class
+ if (erasureIsClass) {
+ while ((currentType = currentType.superclass()) != null) {
+ if (currentType.erasure().id == erasureId) return currentType;
+ }
+ return null;
+ }
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ } while ((currentType = currentType.superclass()) != null);
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ if ((currentType = interfaces[j]).erasure().id == erasureId)
+ return currentType;
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ return null;
+}
+/**
+ * Find supertype which erases to a given type, or null if not found
+ */
+public ReferenceBinding findSuperTypeErasingTo(ReferenceBinding erasure) {
+
+ if (erasure() == erasure) return this;
+ ReferenceBinding currentType = this;
+ if (erasure.isClass()) {
+ while ((currentType = currentType.superclass()) != null) {
+ if (currentType.erasure() == erasure) return currentType;
+ }
+ return null;
+ }
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ } while ((currentType = currentType.superclass()) != null);
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ if ((currentType = interfaces[j]).erasure() == erasure)
+ return currentType;
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ return null;
+}
+
public final int getAccessFlags() {
return modifiers & AccJustFlag;
}
@@ -317,22 +470,17 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
return null;
}
public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+ return getExactMethod(selector, argumentTypes, null);
+}
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
return null;
}
public FieldBinding getField(char[] fieldName, boolean needResolve) {
return null;
}
/**
- * Answer the file name which defines the type.
- *
- * The path part (optional) must be separated from the actual
- * file proper name by a java.io.File.separator.
- *
- * The proper file name includes the suffix extension (e.g. ".java")
- *
- * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
+ * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
*/
-
public char[] getFileName() {
return fileName;
}
@@ -352,12 +500,30 @@ public PackageBinding getPackage() {
public boolean hasMemberTypes() {
return false;
}
+public TypeVariableBinding getTypeVariable(char[] variableName) {
+ TypeVariableBinding[] typeVariables = typeVariables();
+ for (int i = typeVariables.length; --i >= 0;)
+ if (CharOperation.equals(typeVariables[i].sourceName, variableName))
+ return typeVariables[i];
+ return null;
+}
+public int hashCode() {
+ // ensure ReferenceBindings hash to the same posiiton as UnresolvedReferenceBindings so they can be replaced without rehashing
+ // ALL ReferenceBindings are unique when created so equals() is the same as ==
+ return (this.compoundName == null || this.compoundName.length == 0)
+ ? super.hashCode()
+ : CharOperation.hashCode(this.compoundName[this.compoundName.length - 1]);
+}
+
+public final boolean hasRestrictedAccess() {
+ return (modifiers & AccRestrictedAccess) != 0;
+}
+
/* Answer true if the receiver implements anInterface or is identical to anInterface.
* If searchHierarchy is true, then also search the receiver's superclasses.
*
* NOTE: Assume that anInterface is an interface.
*/
-
public boolean implementsInterface(ReferenceBinding anInterface, boolean searchHierarchy) {
if (this == anInterface)
return true;
@@ -377,7 +543,7 @@ public boolean implementsInterface(ReferenceBinding anInterface, boolean searchH
for (int i = 0; i <= lastPosition; i++) {
ReferenceBinding[] interfaces = interfacesToVisit[i];
for (int j = 0, length = interfaces.length; j < length; j++) {
- if ((currentType = interfaces[j]) == anInterface)
+ if ((currentType = interfaces[j]).isEquivalentTo(anInterface))
return true;
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
@@ -409,66 +575,72 @@ boolean implementsMethod(MethodBinding method) {
public final boolean isAbstract() {
return (modifiers & AccAbstract) != 0;
}
+public boolean isAnnotationType() {
+ return (modifiers & AccAnnotation) != 0;
+}
public final boolean isAnonymousType() {
return (tagBits & IsAnonymousType) != 0;
}
public final boolean isBinaryBinding() {
return (tagBits & IsBinaryBinding) != 0;
}
-public final boolean isClass() {
- return (modifiers & AccInterface) == 0;
+public boolean isClass() {
+ return (modifiers & (AccInterface | AccAnnotation | AccEnum)) == 0;
+}
+/*
+ * Returns true if the type hierarchy is being connected
+ */
+public boolean isHierarchyBeingConnected() {
+ return (this.tagBits & EndHierarchyCheck) == 0 && (this.tagBits & BeginHierarchyCheck) != 0;
}
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
-
-public boolean isCompatibleWith(TypeBinding right) {
- if (right == this)
+public boolean isCompatibleWith(TypeBinding otherType) {
+
+ if (otherType == this)
return true;
- if (right.id == T_Object)
+ if (otherType.id == T_JavaLangObject)
return true;
- if (!(right instanceof ReferenceBinding))
+ if (!(otherType instanceof ReferenceBinding))
return false;
-
- ReferenceBinding referenceBinding = (ReferenceBinding) right;
- if (referenceBinding.isInterface())
- return implementsInterface(referenceBinding, true);
+ ReferenceBinding otherReferenceType = (ReferenceBinding) otherType;
+ if (this.isEquivalentTo(otherReferenceType)) return true;
+ if (otherReferenceType.isWildcard()) {
+ return false; // should have passed equivalence check above if wildcard
+ }
+ if (otherReferenceType.isInterface())
+ return implementsInterface(otherReferenceType, true);
if (isInterface()) // Explicit conversion from an interface to a class is not allowed
return false;
- return referenceBinding.isSuperclassOf(this);
+ return otherReferenceType.isSuperclassOf(this);
}
+
/* Answer true if the receiver has default visibility
*/
-
public final boolean isDefault() {
return (modifiers & (AccPublic | AccProtected | AccPrivate)) == 0;
}
+
/* Answer true if the receiver is a deprecated type
*/
-
public final boolean isDeprecated() {
return (modifiers & AccDeprecated) != 0;
}
+public boolean isEnum() {
+ return (modifiers & AccEnum) != 0;
+}
/* Answer true if the receiver is final and cannot be subclassed
*/
-
public final boolean isFinal() {
return (modifiers & AccFinal) != 0;
}
-public final boolean isInterface() {
- return (modifiers & AccInterface) != 0;
-}
-public final boolean isLocalType() {
- return (tagBits & IsLocalType) != 0;
-}
-public final boolean isMemberType() {
- return (tagBits & IsMemberType) != 0;
-}
-public final boolean isNestedType() {
- return (tagBits & IsNestedType) != 0;
+public boolean isInterface() {
+ // only consider strict interfaces
+ return (modifiers & (AccInterface | AccAnnotation)) == AccInterface;
}
+
/* Answer true if the receiver has private visibility
*/
-
public final boolean isPrivate() {
return (modifiers & AccPrivate) != 0;
}
@@ -508,13 +680,13 @@ public final boolean isStrictfp() {
* NOTE: Object.isSuperclassOf(Object) -> false
*/
-public boolean isSuperclassOf(ReferenceBinding type) {
- do {
- if (this == (type = type.superclass())) return true;
- } while (type != null);
-
+public boolean isSuperclassOf(ReferenceBinding otherType) {
+ while ((otherType = otherType.superclass()) != null) {
+ if (otherType.isEquivalentTo(this)) return true;
+ }
return false;
}
+
/* Answer true if the receiver is deprecated (or any of its enclosing types)
*/
@@ -525,6 +697,26 @@ public final boolean isViewedAsDeprecated() {
public ReferenceBinding[] memberTypes() {
return NoMemberTypes;
}
+
+/**
+ * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary
+ */
+public boolean needsUncheckedConversion(TypeBinding targetType) {
+ if (this == targetType) return false;
+ if (!this.isPartOfRawType()) return false;
+ if (!(targetType instanceof ReferenceBinding))
+ return false;
+ TypeBinding compatible = this.findSuperTypeErasingTo((ReferenceBinding)targetType.erasure());
+ if (compatible == null)
+ return false;
+ do {
+ if (compatible.isRawType() && (targetType.isBoundParameterizedType() || targetType.isGenericType())) {
+ return true;
+ }
+ } while ((compatible = compatible.enclosingType()) != null && (targetType = targetType.enclosingType()) != null);
+ return false;
+}
+
public MethodBinding[] methods() {
return NoMethods;
}
@@ -540,16 +732,50 @@ public char[] qualifiedSourceName() {
return sourceName();
}
-public char[] readableName() /*java.lang.Object*/ {
- if (isMemberType())
- return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
- return CharOperation.concatWith(compoundName, '.');
+public char[] readableName() /*java.lang.Object, p.X */ {
+ char[] readableName;
+ if (isMemberType()) {
+ readableName = CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+ } else {
+ readableName = CharOperation.concatWith(compoundName, '.');
+ }
+ TypeVariableBinding[] typeVars;
+ if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(readableName).append('<');
+ for (int i = 0, length = typeVars.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(typeVars[i].readableName());
+ }
+ nameBuffer.append('>');
+ int nameLength = nameBuffer.length();
+ readableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, readableName, 0);
+ }
+ return readableName;
}
public char[] shortReadableName() /*Object*/ {
- if (isMemberType())
- return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
- return sourceName;
+ char[] shortReadableName;
+ if (isMemberType()) {
+ shortReadableName = CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+ } else {
+ shortReadableName = this.sourceName;
+ }
+ TypeVariableBinding[] typeVars;
+ if ((typeVars = this.typeVariables()) != NoTypeVariables) {
+ StringBuffer nameBuffer = new StringBuffer(10);
+ nameBuffer.append(shortReadableName).append('<');
+ for (int i = 0, length = typeVars.length; i < length; i++) {
+ if (i > 0) nameBuffer.append(',');
+ nameBuffer.append(typeVars[i].shortReadableName());
+ }
+ nameBuffer.append('>');
+ int nameLength = nameBuffer.length();
+ shortReadableName = new char[nameLength];
+ nameBuffer.getChars(0, nameLength, shortReadableName, 0);
+ }
+ return shortReadableName;
}
/* Answer the receiver's signature.
@@ -566,6 +792,7 @@ public char[] signature() /* Ljava/lang/Object; */ {
public char[] sourceName() {
return sourceName;
}
+
public ReferenceBinding superclass() {
return null;
}
@@ -583,6 +810,7 @@ public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
return null; // is null if no enclosing instances are required
}
+
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
return methods();
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index bfbb0b5..9b0209f 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -10,6 +10,11 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -20,22 +25,19 @@ import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
public abstract class Scope
- implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
+ implements BaseTypes, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
public final static int BLOCK_SCOPE = 1;
- public final static int METHOD_SCOPE = 2;
public final static int CLASS_SCOPE = 3;
public final static int COMPILATION_UNIT_SCOPE = 4;
+ public final static int METHOD_SCOPE = 2;
- public int kind;
- public Scope parent;
-
- protected Scope(int kind, Scope parent) {
- this.kind = kind;
- this.parent = parent;
- }
+ public final static int NOT_COMPATIBLE = -1;
+ public final static int COMPATIBLE = 0;
+ public final static int AUTOBOX_COMPATIBLE = 1;
+ public final static int VARARGS_COMPATIBLE = 2;
- /* Answer an int describing the relationship between the given types.
+ /* Answer an int describing the relationship between the given types.
*
* NotRelated
* EqualOrMoreSpecific : left is compatible with right
@@ -49,22 +51,128 @@ public abstract class Scope
return NotRelated;
}
- // Internal use only
- protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
- if (parameters == arguments)
- return true;
+ /**
+ * Returns an array of types, where original types got substituted given a substitution.
+ * Only allocate an array if anything is different.
+ */
+ public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
+ ReferenceBinding[] substitutedTypes = originalTypes;
+ for (int i = 0, length = originalTypes.length; i < length; i++) {
+ ReferenceBinding originalType = originalTypes[i];
+ ReferenceBinding substitutedParameter = (ReferenceBinding)substitution.substitute(originalType);
+ if (substitutedParameter != originalType) {
+ if (substitutedTypes == originalTypes) {
+ System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
+ }
+ substitutedTypes[i] = substitutedParameter;
+ } else if (substitutedTypes != originalTypes) {
+ substitutedTypes[i] = originalType;
+ }
+ }
+ return substitutedTypes;
+ }
+
+ /**
+ * Returns an array of types, where original types got substituted given a substitution.
+ * Only allocate an array if anything is different.
+ */
+ public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
+ TypeBinding[] substitutedTypes = originalTypes;
+ for (int i = 0, length = originalTypes.length; i < length; i++) {
+ TypeBinding originalType = originalTypes[i];
+ TypeBinding substitutedParameter = substitution.substitute(originalType);
+ if (substitutedParameter != originalType) {
+ if (substitutedTypes == originalTypes) {
+ System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
+ }
+ substitutedTypes[i] = substitutedParameter;
+ } else if (substitutedTypes != originalTypes) {
+ substitutedTypes[i] = originalType;
+ }
+ }
+ return substitutedTypes;
+ }
- int length = parameters.length;
- if (length != arguments.length)
- return false;
+ public int kind;
+ public Scope parent;
+
+ protected Scope(int kind, Scope parent) {
+ this.kind = kind;
+ this.parent = parent;
+ }
- for (int i = 0; i < length; i++)
- if (parameters[i] != arguments[i])
- if (!arguments[i].isCompatibleWith(parameters[i]))
- return false;
- return true;
+ /*
+ * Boxing primitive
+ */
+ public int boxing(int id) {
+ switch (id) {
+ case T_int :
+ return T_JavaLangInteger;
+ case T_byte :
+ return T_JavaLangByte;
+ case T_short :
+ return T_JavaLangShort;
+ case T_char :
+ return T_JavaLangCharacter;
+ case T_long :
+ return T_JavaLangLong;
+ case T_float :
+ return T_JavaLangFloat;
+ case T_double :
+ return T_JavaLangDouble;
+ case T_boolean :
+ return T_JavaLangBoolean;
+ case T_void :
+ return T_JavaLangVoid;
+ }
+ return id;
}
-
+ /*
+ * Boxing primitive
+ */
+ public TypeBinding boxing(TypeBinding type) {
+ TypeBinding boxedType;
+ switch (type.id) {
+ case T_int :
+ boxedType = environment().getType(JAVA_LANG_INTEGER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_INTEGER, NotFound);
+ case T_byte :
+ boxedType = environment().getType(JAVA_LANG_BYTE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BYTE, NotFound);
+ case T_short :
+ boxedType = environment().getType(JAVA_LANG_SHORT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_SHORT, NotFound);
+ case T_char :
+ boxedType = environment().getType(JAVA_LANG_CHARACTER);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_CHARACTER, NotFound);
+ case T_long :
+ boxedType = environment().getType(JAVA_LANG_LONG);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_LONG, NotFound);
+ case T_float :
+ boxedType = environment().getType(JAVA_LANG_FLOAT);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_FLOAT, NotFound);
+ case T_double :
+ boxedType = environment().getType(JAVA_LANG_DOUBLE);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_DOUBLE, NotFound);
+ case T_boolean :
+ boxedType = environment().getType(JAVA_LANG_BOOLEAN);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_BOOLEAN, NotFound);
+ case T_void :
+ boxedType = environment().getType(JAVA_LANG_VOID);
+ if (boxedType != null) return boxedType;
+ return new ProblemReferenceBinding( JAVA_LANG_VOID, NotFound);
+ }
+ return type;
+ }
+
public final ClassScope classScope() {
Scope scope = this;
do {
@@ -97,16 +205,264 @@ public abstract class Scope
return (CompilationUnitScope) lastScope;
}
- public ArrayBinding createArray(TypeBinding type, int dimension) {
- if (!type.isValidBinding())
- return new ArrayBinding(type, dimension);
- return environment().createArrayType(type, dimension);
+ /**
+ * Internal use only
+ * Given a method, returns null if arguments cannot be converted to parameters.
+ * Will answer a subsituted method in case the method was generic and type inference got triggered;
+ * in case the method was originally compatible, then simply answer it back.
+ */
+ protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
+
+ TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
+ TypeBinding[] parameters = method.parameters;
+ TypeVariableBinding[] typeVariables = method.typeVariables;
+ if (parameters == arguments
+ && (method.returnType.tagBits & HasTypeVariable) == 0
+ && genericTypeArguments == null
+ && typeVariables == NoTypeVariables)
+ return method;
+
+ int argLength = arguments.length;
+ int paramLength = parameters.length;
+ boolean isVarArgs = method.isVarargs();
+ if (argLength != paramLength)
+ if (!isVarArgs || argLength < paramLength - 1)
+ return null; // incompatible
+
+ if (typeVariables != NoTypeVariables) { // generic method
+ method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
+ if (method == null) return null; // incompatible
+ if (!method.isValidBinding()) return method; // bound check issue is taking precedence
+ parameters = method.parameters; // reacquire them after type inference has performed
+ } else if (genericTypeArguments != null) {
+ if (method instanceof ParameterizedGenericMethodBinding) {
+ if (!((ParameterizedGenericMethodBinding) method).wasInferred) {
+ // attempt to invoke generic method of raw type with type hints foo()
+ return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeArgumentsForRawGenericMethod);
+ }
+ } else {
+ return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeParameterArityMismatch);
+ }
+ }
+
+ if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE)
+ return method;
+ if (genericTypeArguments != null)
+ return new ProblemMethodBinding(method, method.selector, arguments, ParameterizedMethodTypeMismatch);
+ return null; // incompatible
+ }
+
+ protected boolean connectTypeVariables(TypeParameter[] typeParameters) {
+ boolean noProblems = true;
+ if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) return true;
+
+ nextVariable : for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+ TypeParameter typeParameter = typeParameters[i];
+ TypeVariableBinding typeVariable = typeParameter.binding;
+ if (typeVariable == null) return false;
+
+ typeVariable.superclass = getJavaLangObject();
+ typeVariable.superInterfaces = NoSuperInterfaces;
+ // set firstBound to the binding of the first explicit bound in parameter declaration
+ typeVariable.firstBound = null; // first bound used to compute erasure
+
+ TypeReference typeRef = typeParameter.type;
+ if (typeRef == null)
+ continue nextVariable;
+ ReferenceBinding superType = this.kind == METHOD_SCOPE
+ ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false/*no bound check*/)
+ : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
+ if (superType == null) {
+ typeVariable.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextVariable;
+ }
+ if (superType.isTypeVariable()) {
+ TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
+ if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
+ problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
+ typeVariable.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextVariable;
+ }
+ }
+ if (superType.isFinal())
+ problemReporter().finalVariableBound(typeVariable, typeRef);
+ typeRef.resolvedType = superType; // hold onto the problem type
+ if (superType.isClass()) {
+ typeVariable.superclass = superType;
+ } else {
+ typeVariable.superInterfaces = new ReferenceBinding[] {superType};
+ typeVariable.modifiers |= AccInterface;
+ }
+ typeVariable.firstBound = superType; // first bound used to compute erasure
+
+ TypeReference[] boundRefs = typeParameter.bounds;
+ if (boundRefs != null) {
+ for (int j = 0, k = boundRefs.length; j < k; j++) {
+ typeRef = boundRefs[j];
+ superType = this.kind == METHOD_SCOPE
+ ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false)
+ : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
+ if (superType == null) {
+ typeVariable.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextVariable;
+ }
+ typeRef.resolvedType = superType; // hold onto the problem type
+ if (superType.isClass()) {
+ problemReporter().boundsMustBeAnInterface(typeRef, superType);
+ typeVariable.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextVariable;
+ }
+ if (superType.isParameterizedType()) {
+ ReferenceBinding match = typeVariable.superclass.findSuperTypeErasingTo((ReferenceBinding) superType.erasure());
+ boolean isCollision = match != null && match != superType;
+ for (int index = typeVariable.superInterfaces.length; !isCollision && --index >= 0;) {
+ ReferenceBinding temp = typeVariable.superInterfaces[index];
+ isCollision = superType != temp && superType.erasure() == temp.erasure();
+ }
+ if (isCollision) {
+ problemReporter().boundHasConflictingArguments(typeRef, superType);
+ typeVariable.tagBits |= HierarchyHasProblems;
+ noProblems = false;
+ continue nextVariable;
+ }
+ }
+ int size = typeVariable.superInterfaces.length;
+ System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
+ typeVariable.superInterfaces[size] = superType;
+ }
+ }
+ }
+ return noProblems;
+ }
+
+ public TypeBinding convertToRawType(TypeBinding type) {
+ int dimension = type.dimensions();
+ TypeBinding originalType = type.leafComponentType();
+ if (originalType instanceof ReferenceBinding) {
+ ReferenceBinding convertedType = (ReferenceBinding) originalType;
+ ReferenceBinding originalEnclosing = originalType.enclosingType();
+ ReferenceBinding convertedEnclosing = originalEnclosing;
+ if (originalEnclosing != null && convertedType.isStatic() && originalEnclosing.isGenericType()) {
+ convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
+ }
+ if (originalType.isGenericType()) {
+ convertedType = environment().createRawType(convertedType, convertedEnclosing);
+ } else if (originalEnclosing != convertedEnclosing) {
+ convertedType = createParameterizedType(convertedType, null, convertedEnclosing);
+ }
+ if (originalType != convertedType) {
+ return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
+ }
+ }
+ return type;
+ }
+// TypeBinding leafType = type.leafComponentType();
+// int dimension = type.dimensions();
+// ReferenceBinding originalEnclosing = leafType.enclosingType();
+// ReferenceBinding convertedEnclosing = originalEnclosing;
+// if (originalEnclosing != null && ((ReferenceBinding)leafType).isStatic()) {
+// convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
+// }
+// if (leafType.isGenericType()) {
+// type = environment().createRawType((ReferenceBinding) leafType, convertedEnclosing);
+// if (dimension > 0)
+// type = createArrayType(type, dimension);
+// } else if (originalEnclosing != convertedEnclosing) {
+// type = createParameterizedType((ReferenceBinding)leafType, null, convertedEnclosing);
+// if (dimension > 0)
+// type = createArrayType(type, dimension);
+// }
+// return type;
+
+ public ArrayBinding createArrayType(TypeBinding type, int dimension) {
+ if (type.isValidBinding())
+ return environment().createArrayType(type, dimension);
+ // do not cache obvious invalid types
+ return new ArrayBinding(type, dimension, environment());
+ }
+
+ public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] arguments, ReferenceBinding enclosingType) {
+ valid: {
+ if (!genericType.isValidBinding()) break valid;
+ for (int i = 0, max = arguments == null ? 0 : arguments.length; i < max; i++)
+ if (!arguments[i].isValidBinding()) break valid;
+ return environment().createParameterizedType(genericType, arguments, enclosingType);
+ }
+ return new ParameterizedTypeBinding(genericType, arguments, enclosingType, environment());
+ }
+
+ public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
+
+ PackageBinding unitPackage = compilationUnitScope().fPackage;
+
+ // do not construct type variables if source < 1.5
+ if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5)
+ return NoTypeVariables;
+ TypeVariableBinding[] typeVariableBindings = NoTypeVariables;
+
+ int length = typeParameters.length;
+ typeVariableBindings = new TypeVariableBinding[length];
+ HashtableOfObject knownTypeParameterNames = new HashtableOfObject(length);
+ int count = 0;
+ nextParameter : for (int i = 0; i < length; i++) {
+ TypeParameter typeParameter = typeParameters[i];
+ TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i);
+ parameterBinding.fPackage = unitPackage;
+ typeParameter.binding = parameterBinding;
+
+ if (knownTypeParameterNames.containsKey(typeParameter.name)) {
+ TypeVariableBinding previousBinding = (TypeVariableBinding) knownTypeParameterNames.get(typeParameter.name);
+ if (previousBinding != null) {
+ for (int j = 0; j < i; j++) {
+ TypeParameter previousParameter = typeParameters[j];
+ if (previousParameter.binding == previousBinding) {
+ problemReporter().duplicateTypeParameterInType(previousParameter);
+ previousParameter.binding = null;
+ break;
+ }
+ }
+ }
+ knownTypeParameterNames.put(typeParameter.name, null); // ensure that the duplicate parameter is found & removed
+ problemReporter().duplicateTypeParameterInType(typeParameter);
+ typeParameter.binding = null;
+ } else {
+ knownTypeParameterNames.put(typeParameter.name, parameterBinding);
+ // remember that we have seen a field with this name
+ if (parameterBinding != null)
+ typeVariableBindings[count++] = parameterBinding;
+ }
+// TODO should offer warnings to inform about hiding declaring, enclosing or member types
+// ReferenceBinding type = sourceType;
+// // check that the member does not conflict with an enclosing type
+// do {
+// if (CharOperation.equals(type.sourceName, memberContext.name)) {
+// problemReporter().hidingEnclosingType(memberContext);
+// continue nextParameter;
+// }
+// type = type.enclosingType();
+// } while (type != null);
+// // check that the member type does not conflict with another sibling member type
+// for (int j = 0; j < i; j++) {
+// if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
+// problemReporter().duplicateNestedType(memberContext);
+// continue nextParameter;
+// }
+// }
+ }
+ if (count != length) {
+ System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
+ }
+ return typeVariableBindings;
}
public final ClassScope enclosingClassScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
- if (scope instanceof ClassScope) return (ClassScope)scope;
+ if (scope instanceof ClassScope) return (ClassScope) scope;
}
return null; // may answer null if no type around
}
@@ -114,7 +470,7 @@ public abstract class Scope
public final MethodScope enclosingMethodScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
- if (scope instanceof MethodScope) return (MethodScope)scope;
+ if (scope instanceof MethodScope) return (MethodScope) scope;
}
return null; // may answer null if no method around
}
@@ -137,28 +493,6 @@ public abstract class Scope
return ((CompilationUnitScope) unitScope).environment;
}
- protected void faultInReceiverType(TypeBinding type) {
- if (type.isArrayType())
- type = ((ArrayBinding) type).leafComponentType;
-
- // check on Begin bit, so as to be resilient with potential illformed binaries containing cycles (67769)
- if (type instanceof BinaryTypeBinding && (type.tagBits & BeginHierarchyCheck) == 0) {
- type.tagBits |= BeginHierarchyCheck;
- // fault in the hierarchy of the type now so we can detect missing types instead of in storeDependencyInfo
- BinaryTypeBinding binaryType = (BinaryTypeBinding) type;
- ReferenceBinding enclosingType = binaryType.enclosingType();
- if (enclosingType != null)
- faultInReceiverType(enclosingType);
- ReferenceBinding superclass = binaryType.superclass();
- if (superclass != null)
- faultInReceiverType(superclass);
- ReferenceBinding[] interfaces = binaryType.superInterfaces();
- for (int i = 0, l = interfaces.length; i < l; i++)
- faultInReceiverType(interfaces[i]);
- type.tagBits |= EndHierarchyCheck;
- }
- }
-
// abstract method lookup lookup (since maybe missing default abstract methods)
public MethodBinding findDefaultAbstractMethod(
ReferenceBinding receiverType,
@@ -175,24 +509,34 @@ public abstract class Scope
matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
currentType = currentType.superclass();
}
+ CompilationUnitScope unitScope = compilationUnitScope();
int foundSize = found.size;
if (foundSize == startFoundSize) {
- if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+ if (matchingMethod != null)
+ unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
return matchingMethod; // maybe null
}
MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
int candidatesCount = 0;
+ MethodBinding problemMethod = null;
// argument type compatibility check
for (int i = startFoundSize; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
- if (areParametersAssignable(methodBinding.parameters, argumentTypes))
- candidates[candidatesCount++] = methodBinding;
+ MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+ if (compatibleMethod != null) {
+ if (compatibleMethod.isValidBinding())
+ candidates[candidatesCount++] = compatibleMethod;
+ else if (problemMethod == null)
+ problemMethod = compatibleMethod;
+ }
}
+
if (candidatesCount == 1) {
- compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+ unitScope.recordTypeReferences(candidates[0].thrownExceptions);
return candidates[0];
}
if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+ if (problemMethod != null) return problemMethod;
int argLength = argumentTypes.length;
nextMethod : for (int i = 0; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
@@ -210,7 +554,10 @@ public abstract class Scope
return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
}
// no need to check for visibility - interface methods are public
- return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
+ boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
+ if (isCompliant14)
+ return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite);
+ return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
}
// Internal use only
@@ -219,14 +566,15 @@ public abstract class Scope
return null; // know it has no member types (nor inherited member types)
SourceTypeBinding enclosingSourceType = enclosingSourceType();
- compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordReference(enclosingType, typeName);
ReferenceBinding memberType = enclosingType.getMemberType(typeName);
if (memberType != null) {
- compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+ unitScope.recordTypeReference(memberType);
if (enclosingSourceType == null
- ? memberType.canBeSeenBy(getCurrentPackage())
- : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
- return memberType;
+ ? memberType.canBeSeenBy(getCurrentPackage())
+ : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+ return memberType;
return new ProblemReferenceBinding(typeName, memberType, NotVisible);
}
return null;
@@ -239,14 +587,24 @@ public abstract class Scope
TypeBinding[] argumentTypes,
InvocationSite invocationSite) {
- faultInReceiverType(receiverType);
- compilationUnitScope().recordTypeReference(receiverType);
- compilationUnitScope().recordTypeReferences(argumentTypes);
- MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordTypeReferences(argumentTypes);
+ MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
if (exactMethod != null) {
- compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
- if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
+ unitScope.recordTypeReferences(exactMethod.thrownExceptions);
+ // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
+ if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
+ if (receiverType.id != T_JavaLangObject
+ && argumentTypes == NoParameters
+ && CharOperation.equals(selector, GETCLASS)
+ && exactMethod.returnType.isParameterizedType()/*1.5*/) {
+ return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this);
+ }
+ // targeting a generic method could find an exact match with variable return type
+ if (exactMethod.typeVariables != NoTypeVariables || invocationSite.genericTypeArguments() != null)
+ exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
return exactMethod;
+ }
}
return null;
}
@@ -263,28 +621,29 @@ public abstract class Scope
*/
public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
if (receiverType.isBaseType()) return null;
+
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordTypeReference(receiverType);
if (receiverType.isArrayType()) {
TypeBinding leafType = receiverType.leafComponentType();
- if (leafType instanceof ReferenceBinding) {
+ if (leafType instanceof ReferenceBinding)
if (!((ReferenceBinding) leafType).canBeSeenBy(this))
return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
- }
if (CharOperation.equals(fieldName, LENGTH))
return ArrayBinding.ArrayLength;
return null;
}
- faultInReceiverType(receiverType);
- compilationUnitScope().recordTypeReference(receiverType);
-
ReferenceBinding currentType = (ReferenceBinding) receiverType;
if (!currentType.canBeSeenBy(this))
return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
if (field != null) {
- if (field.canBeSeenBy(currentType, invocationSite, this))
- return field;
+ if (invocationSite == null
+ ? field.canBeSeenBy(getCurrentPackage())
+ : field.canBeSeenBy(currentType, invocationSite, this))
+ return field;
return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
}
// collect all superinterfaces of receiverType until the field is found in a supertype
@@ -296,21 +655,21 @@ public abstract class Scope
// we could hold onto the not visible field for extra error reporting
while (keepLooking) {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
+ ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
+ itsInterfaces = currentType.superInterfaces();
+ }
if (itsInterfaces != NoSuperInterfaces) {
if (interfacesToVisit == null)
interfacesToVisit = new ReferenceBinding[5][];
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
if ((currentType = currentType.superclass()) == null)
break;
+ unitScope.recordTypeReference(currentType);
if ((field = currentType.getField(fieldName, needResolve)) != null) {
keepLooking = false;
if (field.canBeSeenBy(receiverType, invocationSite, this)) {
@@ -334,6 +693,7 @@ public abstract class Scope
if ((anInterface.tagBits & InterfaceVisited) == 0) {
// if interface as not already been visited
anInterface.tagBits |= InterfaceVisited;
+ unitScope.recordTypeReference(anInterface);
if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
if (visibleField == null) {
visibleField = field;
@@ -345,12 +705,7 @@ public abstract class Scope
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != NoSuperInterfaces) {
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
}
@@ -382,14 +737,15 @@ public abstract class Scope
SourceTypeBinding enclosingSourceType = enclosingSourceType();
PackageBinding currentPackage = getCurrentPackage();
- compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordReference(enclosingType, typeName);
ReferenceBinding memberType = enclosingType.getMemberType(typeName);
if (memberType != null) {
- compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+ unitScope.recordTypeReference(memberType);
if (enclosingSourceType == null
- ? memberType.canBeSeenBy(currentPackage)
- : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
- return memberType;
+ ? memberType.canBeSeenBy(currentPackage)
+ : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+ return memberType;
return new ProblemReferenceBinding(typeName, memberType, NotVisible);
}
@@ -403,24 +759,23 @@ public abstract class Scope
// we could hold onto the not visible field for extra error reporting
while (keepLooking) {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
+ ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
+ itsInterfaces = currentType.superInterfaces();
+ }
if (itsInterfaces != NoSuperInterfaces) {
if (interfacesToVisit == null)
interfacesToVisit = new ReferenceBinding[5][];
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
if ((currentType = currentType.superclass()) == null)
break;
- compilationUnitScope().recordReference(currentType.compoundName, typeName);
+ unitScope.recordReference(currentType, typeName);
if ((memberType = currentType.getMemberType(typeName)) != null) {
- compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+ unitScope.recordTypeReference(memberType);
keepLooking = false;
if (enclosingSourceType == null
? memberType.canBeSeenBy(currentPackage)
@@ -444,9 +799,9 @@ public abstract class Scope
if ((anInterface.tagBits & InterfaceVisited) == 0) {
// if interface as not already been visited
anInterface.tagBits |= InterfaceVisited;
- compilationUnitScope().recordReference(anInterface.compoundName, typeName);
+ unitScope.recordReference(anInterface, typeName);
if ((memberType = anInterface.getMemberType(typeName)) != null) {
- compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+ unitScope.recordTypeReference(memberType);
if (visibleMemberType == null) {
visibleMemberType = memberType;
} else {
@@ -457,12 +812,7 @@ public abstract class Scope
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != NoSuperInterfaces) {
if (++lastPosition == interfacesToVisit.length)
- System.arraycopy(
- interfacesToVisit,
- 0,
- interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
- 0,
- lastPosition);
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
interfacesToVisit[lastPosition] = itsInterfaces;
}
}
@@ -495,13 +845,13 @@ public abstract class Scope
ReferenceBinding currentType = receiverType;
MethodBinding matchingMethod = null;
- ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
+ ObjectVector found = new ObjectVector(); //TODO (kent) should rewrite to remove #matchingMethod since found is allocated anyway
- faultInReceiverType(receiverType);
- compilationUnitScope().recordTypeReference(receiverType);
- compilationUnitScope().recordTypeReferences(argumentTypes);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordTypeReferences(argumentTypes);
if (currentType.isInterface()) {
+ unitScope.recordTypeReference(currentType);
MethodBinding[] currentMethods = currentType.getMethods(selector);
int currentLength = currentMethods.length;
if (currentLength == 1) {
@@ -513,31 +863,31 @@ public abstract class Scope
currentType = getJavaLangObject();
}
- boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
+ boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
// superclass lookup
ReferenceBinding classHierarchyStart = currentType;
while (currentType != null) {
+ unitScope.recordTypeReference(currentType);
MethodBinding[] currentMethods = currentType.getMethods(selector);
int currentLength = currentMethods.length;
-
- /*
- * if 1.4 compliant, must filter out redundant protected methods from superclasses
- */
- if (isCompliant14){
- nextMethod: for (int i = 0; i < currentLength; i++){
+
+ if (isCompliant14 && matchingMethod != null || found.size > 0) {
+ nextMethod: for (int i = 0; i < currentLength; i++) {
MethodBinding currentMethod = currentMethods[i];
+ // if 1.4 compliant, must filter out redundant protected methods from superclasses
// protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
// when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
- if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
- if (matchingMethod != null){
- if (currentMethod.areParametersEqual(matchingMethod)){
+ // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
+ // BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
+ if (matchingMethod != null) {
+ if (currentMethod.areParametersEqual(matchingMethod)) {
currentLength--;
currentMethods[i] = null; // discard this match
continue nextMethod;
}
} else {
for (int j = 0, max = found.size; j < max; j++) {
- if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
+ if (((MethodBinding) found.elementAt(j)).areParametersEqual(currentMethod)) {
currentLength--;
currentMethods[i] = null;
continue nextMethod;
@@ -546,7 +896,7 @@ public abstract class Scope
}
}
}
-
+
if (currentLength == 1 && matchingMethod == null && found.size == 0) {
matchingMethod = currentMethods[0];
} else if (currentLength > 0) {
@@ -573,41 +923,65 @@ public abstract class Scope
MethodBinding[] candidates = null;
int candidatesCount = 0;
boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
+ MethodBinding problemMethod = null;
if (foundSize > 0) {
// argument type compatibility check
for (int i = 0; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
- if (areParametersAssignable(methodBinding.parameters, argumentTypes)) {
- switch (candidatesCount) {
- case 0:
- matchingMethod = methodBinding; // if only one match, reuse matchingMethod
- checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
- break;
- case 1:
- candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
- candidates[0] = matchingMethod; // copy back
- matchingMethod = null;
- // fall through
- default:
- candidates[candidatesCount] = methodBinding;
+ MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+ if (compatibleMethod != null) {
+ if (compatibleMethod.isValidBinding()) {
+ switch (candidatesCount) {
+ case 0:
+ matchingMethod = compatibleMethod; // if only one match, reuse matchingMethod
+ checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
+ break;
+ case 1:
+ candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
+ candidates[0] = matchingMethod; // copy back
+ matchingMethod = null;
+ // fall through
+ default:
+ candidates[candidatesCount] = compatibleMethod;
+ }
+ candidatesCount++;
+ } else if (problemMethod == null) {
+ problemMethod = compatibleMethod;
}
- candidatesCount++;
}
}
}
+ if (candidatesCount > 0)
+ problemMethod = null; // forget the problem method if candidates were found
+
// if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
if (matchingMethod != null) {
- if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
+ if (!checkedMatchingMethod) {
+ MethodBinding compatibleMethod = computeCompatibleMethod(matchingMethod, argumentTypes, invocationSite);
+ if (compatibleMethod != null) {
+ if (compatibleMethod.isValidBinding()) {
+ matchingMethod = compatibleMethod;
+ checkedMatchingMethod = true;
+ } else {
+ problemMethod = compatibleMethod;
+ }
+ }
+ }
+ if (checkedMatchingMethod) {
// (if no default abstract) must explicitly look for one instead, which could be a better match
if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
// ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
- MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);
+ MethodBinding interfaceMethod =
+ findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);
if (interfaceMethod != null) return interfaceMethod;
- compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+ unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
return matchingMethod;
}
}
- return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+ matchingMethod =
+ findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+ if (matchingMethod != null) return matchingMethod;
+ return problemMethod;
}
// no match was found, try to find a close match when the parameter order is wrong or missing some parameters
@@ -615,6 +989,7 @@ public abstract class Scope
MethodBinding interfaceMethod =
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
if (interfaceMethod != null) return interfaceMethod;
+ if (problemMethod != null) return problemMethod;
int argLength = argumentTypes.length;
foundSize = found.size;
@@ -631,9 +1006,23 @@ public abstract class Scope
}
return methodBinding;
}
+ if (found.size == 0) return null;
return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
}
+ // check for duplicate parameterized methods
+ if (unitScope.environment.options.sourceLevel >= ClassFileConstants.JDK1_5) {
+ for (int i = 0; i < candidatesCount; i++) {
+ MethodBinding current = candidates[i];
+ if (current instanceof ParameterizedGenericMethodBinding)
+ current = ((ParameterizedGenericMethodBinding) current).originalMethod;
+ if (current instanceof ParameterizedMethodBinding)
+ for (int j = i + 1; j < candidatesCount; j++)
+ if (current.declaringClass == candidates[j].declaringClass && current.areParametersEqual(candidates[j]))
+ return new ProblemMethodBinding(candidates[i].selector, candidates[i].parameters, Ambiguous);
+ }
+ }
+
// tiebreak using visibility check
int visiblesCount = 0;
for (int i = 0; i < candidatesCount; i++) {
@@ -647,7 +1036,7 @@ public abstract class Scope
}
}
if (visiblesCount == 1) {
- compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+ unitScope.recordTypeReferences(candidates[0].thrownExceptions);
return candidates[0];
}
if (visiblesCount == 0) {
@@ -657,10 +1046,10 @@ public abstract class Scope
return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
}
if (isCompliant14)
- return mostSpecificMethodBinding(candidates, visiblesCount);
+ return mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite);
return candidates[0].declaringClass.isClass()
- ? mostSpecificClassMethodBinding(candidates, visiblesCount)
- : mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
+ ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
+ : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
}
// Internal use only
@@ -680,15 +1069,27 @@ public abstract class Scope
MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
if (methodBinding != null) {
// handle the method clone() specially... cannot be protected or throw exceptions
- if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
- return new UpdatedMethodBinding(
- environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
- (methodBinding.modifiers ^ AccProtected) | AccPublic,
- CLONE,
- methodBinding.returnType,
- argumentTypes,
- null,
- object);
+ if (argumentTypes == NoParameters) {
+ switch (selector[0]) {
+ case 'c':
+ if (CharOperation.equals(selector, CLONE)) {
+ return new UpdatedMethodBinding(
+ environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
+ (methodBinding.modifiers & ~AccProtected) | AccPublic,
+ CLONE,
+ methodBinding.returnType,
+ argumentTypes,
+ null,
+ object);
+ }
+ break;
+ case 'g':
+ if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) {
+ return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
+ }
+ break;
+ }
+ }
if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
return methodBinding;
}
@@ -697,18 +1098,15 @@ public abstract class Scope
if (methodBinding == null)
return new ProblemMethodBinding(selector, argumentTypes, NotFound);
if (methodBinding.isValidBinding()) {
- if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
- return new ProblemMethodBinding(
- methodBinding,
- selector,
- argumentTypes,
- NotFound);
+ MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+ if (compatibleMethod == null)
+ return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
+ if (!compatibleMethod.isValidBinding())
+ return compatibleMethod;
+
+ methodBinding = compatibleMethod;
if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
- return new ProblemMethodBinding(
- methodBinding,
- selector,
- methodBinding.parameters,
- NotVisible);
+ return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
}
return methodBinding;
}
@@ -738,6 +1136,7 @@ public abstract class Scope
// if interface as not already been visited
currentType.tagBits |= InterfaceVisited;
+ compilationUnitScope().recordTypeReference(currentType);
MethodBinding[] currentMethods = currentType.getMethods(selector);
int currentLength = currentMethods.length;
if (currentLength == 1 && matchingMethod == null && found.size == 0) {
@@ -795,7 +1194,7 @@ public abstract class Scope
return null;
}
- public TypeBinding getBaseType(char[] name) {
+ public static TypeBinding getBaseType(char[] name) {
// list should be optimized (with most often used first)
int length = name.length;
if (length > 2 && length < 8) {
@@ -858,7 +1257,7 @@ public abstract class Scope
}
/* API
- *
+ *
* Answer the binding that corresponds to the argument name.
* flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
* Only bindings corresponding to the mask can be answered.
@@ -881,10 +1280,10 @@ public abstract class Scope
try {
Binding binding = null;
FieldBinding problemField = null;
- if ((mask & VARIABLE) != 0) {
+ if ((mask & Binding.VARIABLE) != 0) {
boolean insideStaticContext = false;
boolean insideConstructorCall = false;
-
+
FieldBinding foundField = null;
// can be a problem field which is answered if a valid field is not found
ProblemFieldBinding foundInsideProblem = null;
@@ -918,10 +1317,25 @@ public abstract class Scope
case CLASS_SCOPE :
ClassScope classScope = (ClassScope) scope;
SourceTypeBinding enclosingType = classScope.referenceContext.binding;
- FieldBinding fieldBinding =
- classScope.findField(enclosingType, name, invocationSite, needResolve);
+ FieldBinding fieldBinding = classScope.findField(enclosingType, name, invocationSite, needResolve);
// Use next line instead if willing to enable protected access accross inner types
// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
+
+// SourceTypeBinding initialType = this.enclosingSourceType();
+// if ((fieldBinding == null || !fieldBinding.isValidBinding()) && enclosingType.hasMemberTypes()) { // check member enums
+// ReferenceBinding[] memberTypes = enclosingType.memberTypes();
+// for (int i = 0, length = memberTypes.length; i < length; i++) {
+// ReferenceBinding memberType = memberTypes[i];
+// if (memberType != initialType && memberType.isEnum()) { // do not find one's field through its enclosing members
+// FieldBinding enumField = ((SourceTypeBinding)memberType).scope.findField(memberType, name, invocationSite, needResolve);
+// if (enumField != null && (enumField.modifiers & AccEnum) != 0) {
+// // grant access to enum constants of enclosing members
+// // TODO (kent) need to revisit to see whether should walk sibling enums and issue an ambiguous match
+// return enumField;
+// }
+// }
+// }
+// }
if (fieldBinding != null) { // skip it if we did not find anything
if (fieldBinding.problemId() == Ambiguous) {
if (foundField == null || foundField.problemId() == NotVisible)
@@ -934,7 +1348,7 @@ public abstract class Scope
name,
InheritedNameHidesEnclosingName);
}
-
+
ProblemFieldBinding insideProblem = null;
if (fieldBinding.isValidBinding()) {
if (!fieldBinding.isStatic()) {
@@ -954,8 +1368,7 @@ public abstract class Scope
NonStaticReferenceInStaticContext);
}
}
- if (enclosingType == fieldBinding.declaringClass
- || environment().options.complianceLevel >= ClassFileConstants.JDK1_4){
+ if (enclosingType == fieldBinding.declaringClass || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
// found a valid field in the 'immediate' scope (ie. not inherited)
// OR in 1.4 mode (inherited shadows enclosing)
if (foundField == null) {
@@ -977,10 +1390,8 @@ public abstract class Scope
InheritedNameHidesEnclosingName);
}
}
-
- if (foundField == null
- || (foundField.problemId() == NotVisible
- && fieldBinding.problemId() != NotVisible)) {
+
+ if (foundField == null || (foundField.problemId() == NotVisible && fieldBinding.problemId() != NotVisible)) {
// only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
foundDepth = depth;
foundActualReceiverType = enclosingType;
@@ -1002,12 +1413,12 @@ public abstract class Scope
}
scope = scope.parent;
}
-
+
if (foundInsideProblem != null)
return foundInsideProblem;
if (foundField != null) {
- if (foundField.isValidBinding()){
- if (foundDepth > 0){
+ if (foundField.isValidBinding()) {
+ if (foundDepth > 0) {
invocationSite.setDepth(foundDepth);
invocationSite.setActualReceiverType(foundActualReceiverType);
}
@@ -1015,24 +1426,69 @@ public abstract class Scope
}
problemField = foundField;
}
+
+ if (environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
+ // at this point the scope is a compilation unit scope & need to check for imported static fields
+ CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+ ImportBinding[] imports = unitScope.imports;
+ if (imports != null) {
+ // check single static imports
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding importBinding = imports[i];
+ if (importBinding.isStatic() && !importBinding.onDemand) {
+ if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
+ if (unitScope.resolveSingleImport(importBinding) != null && importBinding.resolvedImport instanceof FieldBinding) {
+ ImportReference importReference = importBinding.reference;
+ if (importReference != null) importReference.used = true;
+ return importBinding.resolvedImport; // already know its visible
+ }
+ }
+ }
+ }
+ // check on demand imports
+ boolean foundInImport = false;
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding importBinding = imports[i];
+ if (importBinding.isStatic() && importBinding.onDemand) {
+ Binding resolvedImport = importBinding.resolvedImport;
+ if (resolvedImport instanceof ReferenceBinding) {
+ FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
+ if (temp != null) {
+ if (!temp.isValidBinding()) {
+ problemField = temp;
+ } else if (temp.isStatic()) {
+ ImportReference importReference = importBinding.reference;
+ if (importReference != null) importReference.used = true;
+ if (foundInImport)
+ // Answer error binding -- import on demand conflict; name found in two import on demand packages.
+ return new ProblemReferenceBinding(name, Ambiguous);
+ foundField = temp;
+ foundInImport = true;
+ }
+ }
+ }
+ }
+ }
+ if (foundField != null) return foundField;
+ }
+ }
}
-
+
// We did not find a local or instance variable.
- if ((mask & TYPE) != 0) {
+ if ((mask & Binding.TYPE) != 0) {
if ((binding = getBaseType(name)) != null)
return binding;
- binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
- if (binding.isValidBinding() || mask == TYPE)
+ binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
+ if (binding.isValidBinding() || mask == Binding.TYPE)
return binding;
// answer the problem type binding if we are only looking for a type
- } else if ((mask & PACKAGE) != 0) {
+ } else if ((mask & Binding.PACKAGE) != 0) {
compilationUnitScope().recordSimpleReference(name);
if ((binding = environment().getTopLevelPackage(name)) != null)
return binding;
}
if (problemField != null) return problemField;
return new ProblemBinding(name, enclosingSourceType(), NotFound);
-
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
@@ -1041,29 +1497,40 @@ public abstract class Scope
public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
try {
- faultInReceiverType(receiverType);
- compilationUnitScope().recordTypeReference(receiverType);
- compilationUnitScope().recordTypeReferences(argumentTypes);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordTypeReference(receiverType);
+ unitScope.recordTypeReferences(argumentTypes);
MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
- if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this))
+ if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
+ // targeting a non generic constructor with type arguments ?
+ if (invocationSite.genericTypeArguments() != null)
+ methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
return methodBinding;
- MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+ }
+ MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
if (methods == NoMethods)
return new ProblemMethodBinding(
- ConstructorDeclaration.ConstantPoolName,
+ TypeConstants.INIT,
argumentTypes,
NotFound);
-
+
MethodBinding[] compatible = new MethodBinding[methods.length];
int compatibleIndex = 0;
- for (int i = 0, length = methods.length; i < length; i++)
- if (areParametersAssignable(methods[i].parameters, argumentTypes))
- compatible[compatibleIndex++] = methods[i];
- if (compatibleIndex == 0)
- return new ProblemMethodBinding(
- ConstructorDeclaration.ConstantPoolName,
- argumentTypes,
- NotFound);
+ MethodBinding problemMethod = null;
+ for (int i = 0, length = methods.length; i < length; i++) {
+ MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
+ if (compatibleMethod != null) {
+ if (compatibleMethod.isValidBinding())
+ compatible[compatibleIndex++] = compatibleMethod;
+ else if (problemMethod == null)
+ problemMethod = compatibleMethod;
+ }
+ }
+ if (compatibleIndex == 0) {
+ if (problemMethod == null)
+ return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound);
+ return problemMethod;
+ }
// need a more descriptive error... cannot convert from X to Y
MethodBinding[] visible = new MethodBinding[compatibleIndex];
@@ -1077,10 +1544,11 @@ public abstract class Scope
if (visibleIndex == 0)
return new ProblemMethodBinding(
compatible[0],
- ConstructorDeclaration.ConstantPoolName,
+ TypeConstants.INIT,
compatible[0].parameters,
NotVisible);
- return mostSpecificClassMethodBinding(visible, visibleIndex);
+ // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding
+ return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite);
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
@@ -1106,26 +1574,22 @@ public abstract class Scope
if (!methodScope.isInsideInitializer()){
// check method modifiers to see if deprecated
MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
- if (context != null) {
+ if (context != null)
return context.modifiers;
- }
} else {
- SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
+ SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
// inside field declaration ? check field modifier to see if deprecated
- if (methodScope.initializedField != null) {
+ if (methodScope.initializedField != null)
return methodScope.initializedField.modifiers;
- }
- if (type != null) {
+ if (type != null)
return type.modifiers;
- }
}
break;
case Scope.CLASS_SCOPE :
ReferenceBinding context = ((ClassScope)this).referenceType().binding;
- if (context != null) {
+ if (context != null)
return context.modifiers;
- }
break;
}
return -1;
@@ -1143,7 +1607,7 @@ public abstract class Scope
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
- }
+ }
}
/* API
@@ -1159,17 +1623,14 @@ public abstract class Scope
*
* If no visible method is discovered, an error binding is answered.
*/
- public MethodBinding getImplicitMethod(
- char[] selector,
- TypeBinding[] argumentTypes,
- InvocationSite invocationSite) {
+ public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
boolean insideStaticContext = false;
boolean insideConstructorCall = false;
MethodBinding foundMethod = null;
- ProblemMethodBinding foundFuzzyProblem = null;
+ MethodBinding foundFuzzyProblem = null;
// the weird method lookup case (matches method name in scope, then arg types, then visibility)
- ProblemMethodBinding foundInsideProblem = null;
+ MethodBinding foundInsideProblem = null;
// inside Constructor call or inside static context
Scope scope = this;
int depth = 0;
@@ -1185,26 +1646,16 @@ public abstract class Scope
SourceTypeBinding receiverType = classScope.referenceContext.binding;
boolean isExactMatch = true;
// retrieve an exact visible match (if possible)
+ // compilationUnitScope().recordTypeReference(receiverType); not needed since receiver is the source type
MethodBinding methodBinding =
(foundMethod == null)
- ? classScope.findExactMethod(
- receiverType,
- selector,
- argumentTypes,
- invocationSite)
- : classScope.findExactMethod(
- receiverType,
- foundMethod.selector,
- foundMethod.parameters,
- invocationSite);
- // ? findExactMethod(receiverType, selector, argumentTypes, invocationSite)
- // : findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
+ ? classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite)
+ : classScope.findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
if (methodBinding == null) {
// answers closest approximation, may not check argumentTypes or visibility
isExactMatch = false;
- methodBinding =
- classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
- // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
+ methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
+ // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
}
if (methodBinding != null) { // skip it if we did not find anything
if (methodBinding.problemId() == Ambiguous) {
@@ -1219,26 +1670,25 @@ public abstract class Scope
argumentTypes,
InheritedNameHidesEnclosingName);
}
- ProblemMethodBinding fuzzyProblem = null;
- ProblemMethodBinding insideProblem = null;
+ MethodBinding fuzzyProblem = null;
+ MethodBinding insideProblem = null;
if (methodBinding.isValidBinding()) {
if (!isExactMatch) {
- if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) {
- if (foundMethod == null || foundMethod.problemId() == NotVisible){
+ MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+ if (compatibleMethod == null) {
+ if (foundMethod == null || foundMethod.problemId() == NotVisible)
// inherited mismatch is reported directly, not looking at enclosing matches
return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
- }
// make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
- fuzzyProblem = new ProblemMethodBinding(selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
-
- } else if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
- // using instead of for visibility check does grant all access to innerclass
- fuzzyProblem =
- new ProblemMethodBinding(
- methodBinding,
- selector,
- methodBinding.parameters,
- NotVisible);
+ fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
+ } else if (!compatibleMethod.isValidBinding()) {
+ fuzzyProblem = compatibleMethod;
+ } else {
+ methodBinding = compatibleMethod;
+ if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
+ // using instead of for visibility check does grant all access to innerclass
+ fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
+ }
}
}
if (fuzzyProblem == null && !methodBinding.isStatic()) {
@@ -1258,10 +1708,10 @@ public abstract class Scope
NonStaticReferenceInStaticContext);
}
}
-
+
if (receiverType == methodBinding.declaringClass
|| (receiverType.getMethods(selector)) != NoMethods
- || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)){
+ || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)) {
// found a valid method in the 'immediate' scope (ie. not inherited)
// OR the receiverType implemented a method with the correct name
// OR in 1.4 mode (inherited visible shadows enclosing)
@@ -1289,12 +1739,10 @@ public abstract class Scope
}
}
- if (foundMethod == null
- || (foundMethod.problemId() == NotVisible
- && methodBinding.problemId() != NotVisible)) {
+ if (foundMethod == null || (foundMethod.problemId() == NotVisible && methodBinding.problemId() != NotVisible)) {
// only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is...
// remember that private methods are visible if defined directly by an enclosing class
- if (depth > 0){
+ if (depth > 0) {
invocationSite.setDepth(depth);
invocationSite.setActualReceiverType(receiverType);
}
@@ -1325,6 +1773,53 @@ public abstract class Scope
return foundInsideProblem;
if (foundMethod != null)
return foundMethod;
+
+ if (insideStaticContext && environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
+ // at this point the scope is a compilation unit scope & need to check for imported static methods
+ CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+ ImportBinding[] imports = unitScope.imports;
+ if (imports != null) {
+ // check on demand imports
+ boolean foundInImport = false;
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding importBinding = imports[i];
+ if (importBinding.isStatic() && importBinding.onDemand) {
+ Binding resolvedImport = importBinding.resolvedImport;
+ if (resolvedImport instanceof ReferenceBinding) {
+ // answers closest approximation, may not check argumentTypes or visibility
+ MethodBinding temp = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite);
+ if (temp != null) {
+ if (!temp.isValidBinding()) {
+ if (foundMethod == null)
+ foundMethod = temp;
+ } else if (temp.isStatic()) {
+ MethodBinding compatibleMethod = computeCompatibleMethod(temp, argumentTypes, invocationSite);
+ if (compatibleMethod != null) {
+ if (compatibleMethod.isValidBinding()) {
+ if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
+ ImportReference importReference = importBinding.reference;
+ if (importReference != null) importReference.used = true;
+ if (foundInImport)
+ // Answer error binding -- import on demand conflict; name found in two import on demand types.
+ return new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, Ambiguous);
+ foundMethod = compatibleMethod;
+ foundInImport = true;
+ } else if (foundMethod == null) {
+ foundMethod = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, NotVisible);
+ }
+ }
+ } else if (foundMethod == null) {
+ foundMethod = new ProblemMethodBinding(temp, selector, argumentTypes, NotFound);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (foundMethod != null)
+ return foundMethod;
+ }
return new ProblemMethodBinding(selector, argumentTypes, NotFound);
}
@@ -1336,7 +1831,16 @@ public abstract class Scope
problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
return null; // will not get here since the above error aborts the compilation
}
-
+
+ public final ReferenceBinding getJavaLangAnnotationAnnotation() {
+ compilationUnitScope().recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION);
+ ReferenceBinding type = environment().getType(JAVA_LANG_ANNOTATION_ANNOTATION);
+ if (type != null) return type;
+
+ problemReporter().isClassPathCorrect(JAVA_LANG_ANNOTATION_ANNOTATION, referenceCompilationUnit());
+ return null; // will not get here since the above error aborts the compilation
+ }
+
public final ReferenceBinding getJavaLangAssertionError() {
compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
@@ -1362,7 +1866,14 @@ public abstract class Scope
problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
return null; // will not get here since the above error aborts the compilation
}
-
+ public final ReferenceBinding getJavaLangEnum() {
+ compilationUnitScope().recordQualifiedReference(JAVA_LANG_ENUM);
+ ReferenceBinding type = environment().getType(JAVA_LANG_ENUM);
+ if (type != null) return type;
+
+ problemReporter().isClassPathCorrect(JAVA_LANG_ENUM, referenceCompilationUnit());
+ return null; // will not get here since the above error aborts the compilation
+ }
public final ReferenceBinding getJavaLangError() {
compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
@@ -1371,7 +1882,14 @@ public abstract class Scope
problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
return null; // will not get here since the above error aborts the compilation
}
-
+ public final ReferenceBinding getJavaLangIterable() {
+ compilationUnitScope().recordQualifiedReference(JAVA_LANG_ITERABLE);
+ ReferenceBinding type = environment().getType(JAVA_LANG_ITERABLE);
+ if (type != null) return type;
+
+ problemReporter().isClassPathCorrect(JAVA_LANG_ITERABLE, referenceCompilationUnit());
+ return null; // will not get here since the above error aborts the compilation
+ }
public final ReferenceBinding getJavaLangObject() {
compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
@@ -1407,6 +1925,14 @@ public abstract class Scope
problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
return null; // will not get here since the above error aborts the compilation
}
+ public final ReferenceBinding getJavaUtilIterator() {
+ compilationUnitScope().recordQualifiedReference(JAVA_UTIL_ITERATOR);
+ ReferenceBinding type = environment().getType(JAVA_UTIL_ITERATOR);
+ if (type != null) return type;
+
+ problemReporter().isClassPathCorrect(JAVA_UTIL_ITERATOR, referenceCompilationUnit());
+ return null; // will not get here since the above error aborts the compilation
+ }
/* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
*/
@@ -1418,11 +1944,13 @@ public abstract class Scope
public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
try {
- if (receiverType.isArrayType())
- return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
if (receiverType.isBaseType())
return new ProblemMethodBinding(selector, argumentTypes, NotFound);
-
+
+ compilationUnitScope().recordTypeReference(receiverType);
+ if (receiverType.isArrayType())
+ return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
+
ReferenceBinding currentType = (ReferenceBinding) receiverType;
if (!currentType.canBeSeenBy(this))
return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
@@ -1431,32 +1959,64 @@ public abstract class Scope
MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
if (methodBinding != null) return methodBinding;
+ // TODO (kent) performance - we are accumulating super methods which are *hidden* during the walk (see testcase from bug 69141)
// answers closest approximation, may not check argumentTypes or visibility
methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
if (methodBinding == null)
return new ProblemMethodBinding(selector, argumentTypes, NotFound);
if (methodBinding.isValidBinding()) {
- if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
- return new ProblemMethodBinding(
- methodBinding,
- selector,
- argumentTypes,
- NotFound);
+ MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
+ if (compatibleMethod == null)
+ return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
+ if (!compatibleMethod.isValidBinding())
+ return compatibleMethod;
+
+ methodBinding = compatibleMethod;
if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
- return new ProblemMethodBinding(
- methodBinding,
- selector,
- methodBinding.parameters,
- NotVisible);
+ return new ProblemMethodBinding( methodBinding, selector, methodBinding.parameters, NotVisible);
}
return methodBinding;
-
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
}
}
+ /* Answer the package from the compoundName or null if it begins with a type.
+ * Intended to be used while resolving a qualified type name.
+ *
+ * NOTE: If a problem binding is returned, senders should extract the compound name
+ * from the binding & not assume the problem applies to the entire compoundName.
+ */
+ public final Binding getPackage(char[][] compoundName) {
+ compilationUnitScope().recordQualifiedReference(compoundName);
+ Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
+ if (binding == null)
+ return new ProblemReferenceBinding(compoundName[0], NotFound);
+ if (!binding.isValidBinding())
+ return (ReferenceBinding) binding;
+
+ if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package
+
+ int currentIndex = 1;
+ PackageBinding packageBinding = (PackageBinding) binding;
+ while (currentIndex < compoundName.length) {
+ binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+ if (binding == null)
+ return new ProblemReferenceBinding(
+ CharOperation.subarray(compoundName, 0, currentIndex),
+ NotFound);
+ if (!binding.isValidBinding())
+ return new ProblemReferenceBinding(
+ CharOperation.subarray(compoundName, 0, currentIndex),
+ binding.problemId());
+ if (!(binding instanceof PackageBinding))
+ return packageBinding;
+ packageBinding = (PackageBinding) binding;
+ }
+ return new ProblemReferenceBinding(compoundName, NotFound);
+ }
+
/* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
* The name provided is a simple source name (e.g., "Object" , "Point", ...)
*/
@@ -1467,7 +2027,34 @@ public abstract class Scope
// Would like to remove this test and require senders to specially handle base types
TypeBinding binding = getBaseType(name);
if (binding != null) return binding;
- return (ReferenceBinding) getTypeOrPackage(name, TYPE);
+ return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE);
+ }
+
+ /* Answer the type binding that corresponds to the given name, starting the lookup in the receiver
+ * or the packageBinding if provided.
+ * The name provided is a simple source name (e.g., "Object" , "Point", ...)
+ */
+ public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
+ if (packageBinding == null)
+ return getType(name);
+
+ Binding binding = packageBinding.getTypeOrPackage(name);
+ if (binding == null)
+ return new ProblemReferenceBinding(
+ CharOperation.arrayConcat(packageBinding.compoundName, name),
+ NotFound);
+ if (!binding.isValidBinding())
+ return new ProblemReferenceBinding(
+ CharOperation.arrayConcat(packageBinding.compoundName, name),
+ binding.problemId());
+
+ ReferenceBinding typeBinding = (ReferenceBinding) binding;
+ if (!typeBinding.canBeSeenBy(this))
+ return new ProblemReferenceBinding(
+ CharOperation.arrayConcat(packageBinding.compoundName, name),
+ typeBinding,
+ NotVisible);
+ return typeBinding;
}
/* Answer the type binding corresponding to the compoundName.
@@ -1475,17 +2062,17 @@ public abstract class Scope
* NOTE: If a problem binding is returned, senders should extract the compound name
* from the binding & not assume the problem applies to the entire compoundName.
*/
- public final TypeBinding getType(char[][] compoundName) {
- int typeNameLength = compoundName.length;
+ public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
if (typeNameLength == 1) {
// Would like to remove this test and require senders to specially handle base types
TypeBinding binding = getBaseType(compoundName[0]);
if (binding != null) return binding;
}
- compilationUnitScope().recordQualifiedReference(compoundName);
+ CompilationUnitScope unitScope = compilationUnitScope();
+ unitScope.recordQualifiedReference(compoundName);
Binding binding =
- getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
+ getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
if (binding == null)
return new ProblemReferenceBinding(compoundName[0], NotFound);
if (!binding.isValidBinding())
@@ -1518,7 +2105,7 @@ public abstract class Scope
// binding is now a ReferenceBinding
ReferenceBinding typeBinding = (ReferenceBinding) binding;
- compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
+ unitScope.recordTypeReference(typeBinding);
if (checkVisibility) // handles the fall through case
if (!typeBinding.canBeSeenBy(this))
return new ProblemReferenceBinding(
@@ -1549,7 +2136,8 @@ public abstract class Scope
final Binding getTypeOrPackage(char[] name, int mask) {
Scope scope = this;
ReferenceBinding foundType = null;
- if ((mask & TYPE) == 0) {
+ boolean insideStaticContext = false;
+ if ((mask & Binding.TYPE) == 0) {
Scope next = scope;
while ((next = scope.parent) != null)
scope = next;
@@ -1557,6 +2145,13 @@ public abstract class Scope
done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
switch (scope.kind) {
case METHOD_SCOPE :
+ MethodScope methodScope = (MethodScope) scope;
+ AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
+ if (methodDecl != null && methodDecl.binding != null) {
+ TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
+ if (typeVariable != null) return typeVariable;
+ }
+ insideStaticContext |= methodScope.isStatic;
case BLOCK_SCOPE :
ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
if (localType != null) {
@@ -1567,7 +2162,24 @@ public abstract class Scope
break;
case CLASS_SCOPE :
SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
- // 6.5.5.1 - simple name favors member type over top-level type in same unit
+ if (sourceType.isHierarchyBeingConnected()) {
+ // type variables take precedence over the source type, ex. class X extends X == class X extends Y
+ TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
+ if (typeVariable != null)
+ return typeVariable;
+ if (CharOperation.equals(name, sourceType.sourceName))
+ return sourceType;
+ break;
+ }
+ // type variables take precedence over member types
+ TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
+ if (typeVariable != null) {
+ if (insideStaticContext) // do not consider this type modifiers: access is legite within same type
+ return new ProblemReferenceBinding(name, NonStaticReferenceInStaticContext);
+ return typeVariable;
+ }
+ insideStaticContext |= (sourceType.modifiers & AccStatic) != 0; // not isStatic()
+ // 6.5.5.1 - member types have precedence over top-level type in same unit
ReferenceBinding memberType = findMemberType(name, sourceType);
if (memberType != null) { // skip it if we did not find anything
if (memberType.problemId() == Ambiguous) {
@@ -1584,10 +2196,9 @@ public abstract class Scope
// OR in 1.4 mode (inherited shadows enclosing)
if (foundType == null)
return memberType;
- if (foundType.isValidBinding())
- // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
- if (foundType != memberType)
- return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+ // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
+ if (foundType.isValidBinding() && foundType != memberType)
+ return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
}
}
if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
@@ -1613,7 +2224,7 @@ public abstract class Scope
CompilationUnitScope unitScope = (CompilationUnitScope) scope;
PackageBinding currentPackage = unitScope.fPackage;
// ask for the imports + name
- if ((mask & TYPE) != 0) {
+ if ((mask & Binding.TYPE) != 0) {
// check single type imports.
ImportBinding[] imports = unitScope.imports;
@@ -1632,9 +2243,10 @@ public abstract class Scope
ImportBinding typeImport = imports[i];
if (!typeImport.onDemand) {
if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
- if (unitScope.resolveSingleTypeImport(typeImport) != null) {
+ if (unitScope.resolveSingleImport(typeImport) != null) {
ImportReference importReference = typeImport.reference;
- if (importReference != null) importReference.used = true;
+ if (importReference != null)
+ importReference.used = true;
return typeImport.resolvedImport; // already know its visible
}
}
@@ -1657,7 +2269,9 @@ public abstract class Scope
Binding resolvedImport = someImport.resolvedImport;
ReferenceBinding temp = resolvedImport instanceof PackageBinding
? findType(name, (PackageBinding) resolvedImport, currentPackage)
- : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
+ : (someImport.isStatic()
+ ? findMemberType(name, (ReferenceBinding) resolvedImport) // static imports are allowed to see inherited member types
+ : findDirectMemberType(name, (ReferenceBinding) resolvedImport));
if (temp != null) {
if (temp.isValidBinding()) {
ImportReference importReference = someImport.reference;
@@ -1678,7 +2292,7 @@ public abstract class Scope
}
unitScope.recordSimpleReference(name);
- if ((mask & PACKAGE) != 0) {
+ if ((mask & Binding.PACKAGE) != 0) {
PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
if (packageBinding != null) return packageBinding;
}
@@ -1689,13 +2303,16 @@ public abstract class Scope
}
// Added for code assist... NOT Public API
+ // DO NOT USE to resolve import references since this method assumes 'A.B' is relative to a single type import of 'p1.A'
+ // when it may actually mean the type B in the package A
+ // use CompilationUnitScope.getImport(char[][]) instead
public final Binding getTypeOrPackage(char[][] compoundName) {
int nameLength = compoundName.length;
if (nameLength == 1) {
TypeBinding binding = getBaseType(compoundName[0]);
if (binding != null) return binding;
}
- Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
+ Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
if (!binding.isValidBinding()) return binding;
int currentIndex = 1;
@@ -1721,7 +2338,17 @@ public abstract class Scope
checkVisibility = true;
}
// binding is now a ReferenceBinding
+ ReferenceBinding qualifiedType = null;
+
ReferenceBinding typeBinding = (ReferenceBinding) binding;
+ if (typeBinding.isGenericType()) {
+ qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
+ } else {
+ qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+ ? this.createParameterizedType(typeBinding, null, qualifiedType)
+ : typeBinding;
+ }
+
if (checkVisibility) // handles the fall through case
if (!typeBinding.canBeSeenBy(this))
return new ProblemReferenceBinding(
@@ -1731,18 +2358,63 @@ public abstract class Scope
while (currentIndex < nameLength) {
typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
+
+ if (typeBinding.isGenericType()) {
+ qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
+ } else {
+ qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
+ ? this.createParameterizedType(typeBinding, null, qualifiedType)
+ : typeBinding;
+ }
+
// checks visibility
- if (!typeBinding.isValidBinding())
+ if (!qualifiedType.isValidBinding())
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
- typeBinding.problemId());
+ qualifiedType.problemId());
}
- return typeBinding;
+ return qualifiedType;
+ }
+
+ // 5.1.10
+ public TypeBinding[] greaterLowerBound(TypeBinding[] types) {
+ if (types == null) return null;
+ int length = types.length;
+ TypeBinding[] result = types;
+ int removed = 0;
+ for (int i = 0; i < length; i++) {
+ TypeBinding iType = result[i];
+ for (int j = 0; j < length; j++) {
+ if (i == j) continue;
+ TypeBinding jType = result[j];
+ if (jType == null) continue;
+ if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
+ if (result == types) { // defensive copy
+ System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
+ }
+ result[j] = null;
+ removed ++;
+ }
+ }
+ }
+ if (removed == 0) return result;
+ TypeBinding[] trimmedResult = new TypeBinding[length - removed];
+ for (int i = 0, index = 0; i < length; i++) {
+ TypeBinding iType = result[i];
+ if (iType != null) {
+ trimmedResult[index++] = iType;
+ }
+ }
+ return trimmedResult;
+ }
+
+ public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
+ return left.isBaseType() != right.isBaseType() && environment().isBoxingCompatibleWith(left, right);
}
/* Answer true if the scope is nested inside a given field declaration.
- * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
- * e.g. during name resolution.
+ * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
+ * e.g. during name resolution.
*/
public final boolean isDefinedInField(FieldBinding field) {
Scope scope = this;
@@ -1763,10 +2435,9 @@ public abstract class Scope
do {
if (scope instanceof MethodScope) {
ReferenceContext refContext = ((MethodScope) scope).referenceContext;
- if (refContext instanceof AbstractMethodDeclaration
- && ((AbstractMethodDeclaration)refContext).binding == method) {
- return true;
- }
+ if (refContext instanceof AbstractMethodDeclaration)
+ if (((AbstractMethodDeclaration) refContext).binding == method)
+ return true;
}
scope = scope.parent;
} while (scope != null);
@@ -1787,8 +2458,7 @@ public abstract class Scope
unitScope = scope;
// test that the enclosingType is not part of the compilation unit
- SourceTypeBinding[] topLevelTypes =
- ((CompilationUnitScope) unitScope).topLevelTypes;
+ SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
for (int i = topLevelTypes.length; --i >= 0;)
if (topLevelTypes[i] == enclosingType)
return true;
@@ -1801,9 +2471,8 @@ public abstract class Scope
Scope scope = this;
do {
if (scope instanceof ClassScope)
- if (((ClassScope) scope).referenceContext.binding == type){
+ if (((ClassScope) scope).referenceContext.binding == type)
return true;
- }
scope = scope.parent;
} while (scope != null);
return false;
@@ -1817,29 +2486,136 @@ public abstract class Scope
if (!methodScope.isInsideInitializer()){
// check method modifiers to see if deprecated
MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
- if (context != null && context.isViewedAsDeprecated()) {
+ if (context != null && context.isViewedAsDeprecated())
return true;
- }
} else {
SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
// inside field declaration ? check field modifier to see if deprecated
- if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) {
+ if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated())
return true;
- }
- if (type != null && type.isViewedAsDeprecated()) {
+ if (type != null && type.isViewedAsDeprecated())
return true;
- }
}
break;
case Scope.CLASS_SCOPE :
ReferenceBinding context = ((ClassScope)this).referenceType().binding;
- if (context != null && context.isViewedAsDeprecated()) {
+ if (context != null && context.isViewedAsDeprecated())
return true;
- }
break;
}
return false;
}
+ private TypeBinding leastContainingInvocation(TypeBinding mec, List invocations) {
+ int length = invocations.size();
+ if (length == 0) return mec;
+ if (length == 1) return (TypeBinding) invocations.get(0);
+ int argLength = mec.typeVariables().length;
+ if (argLength == 0) return mec; // should be caught by no invocation check
+
+ // infer proper parameterized type from invocations
+ TypeBinding[] bestArguments = new TypeBinding[argLength];
+ for (int i = 0; i < length; i++) {
+ TypeBinding invocation = (TypeBinding)invocations.get(i);
+ TypeVariableBinding[] invocationVariables = invocation.typeVariables();
+ if (invocation.isGenericType()) {
+ for (int j = 0; j < argLength; j++) {
+ TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j);
+ if (bestArgument == null) return null;
+ bestArguments[j] = bestArgument;
+ }
+ } else if (invocation.isParameterizedType()) {
+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
+ for (int j = 0; j < argLength; j++) {
+ TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j);
+ if (bestArgument == null) return null;
+ bestArguments[j] = bestArgument;
+ }
+ } else if (invocation.isRawType()) {
+ return invocation; // raw type is taking precedence
+ }
+ }
+ return createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, null);
+ }
+
+ // JLS 15.12.2
+ private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank) {
+ if (u == null) return v;
+ if (u == v) return u;
+ if (v.isWildcard()) {
+ WildcardBinding wildV = (WildcardBinding) v;
+ if (u.isWildcard()) {
+ WildcardBinding wildU = (WildcardBinding) u;
+ switch (wildU.kind) {
+ // ? extends U
+ case Wildcard.EXTENDS :
+ switch(wildV.kind) {
+ // ? extends U, ? extends V
+ case Wildcard.EXTENDS :
+ TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound});
+ if (lub == null) return null;
+ return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
+ // ? extends U, ? SUPER V
+ case Wildcard.SUPER :
+ if (wildU.bound == wildV.bound) return wildU.bound;
+ return environment().createWildcard(genericType, rank, null, Wildcard.UNBOUND);
+ }
+ break;
+ // ? super U
+ case Wildcard.SUPER :
+ // ? super U, ? super V
+ if (wildU.kind == Wildcard.SUPER) {
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
+ if (glb == null) return null;
+ return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
+ }
+ }
+ } else {
+ switch (wildV.kind) {
+ // U, ? extends V
+ case Wildcard.EXTENDS :
+ TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound});
+ if (lub == null) return null;
+ return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
+ // U, ? super V
+ case Wildcard.SUPER :
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
+ if (glb == null) return null;
+ return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
+ case Wildcard.UNBOUND :
+ }
+ }
+ } else if (u.isWildcard()) {
+ WildcardBinding wildU = (WildcardBinding) u;
+ switch (wildU.kind) {
+ // U, ? extends V
+ case Wildcard.EXTENDS :
+ TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v});
+ if (lub == null) return null;
+ return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
+ // U, ? super V
+ case Wildcard.SUPER :
+ TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
+ if (glb == null) return null;
+ return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
+ case Wildcard.UNBOUND :
+ }
+ }
+ TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v});
+ if (lub == null) return null;
+ return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
+ }
+
+ // 15.12.2
+ public TypeBinding lowerUpperBound(TypeBinding[] types) {
+
+ if (types.length == 1) {
+ TypeBinding type = types[0];
+ return type == null ? VoidBinding : type;
+ }
+ ArrayList invocations = new ArrayList(1);
+ TypeBinding mec = minimalErasedCandidate(types, invocations);
+ return leastContainingInvocation(mec, invocations);
+ }
public final MethodScope methodScope() {
Scope scope = this;
@@ -1851,6 +2627,143 @@ public abstract class Scope
return null;
}
+ /**
+ * Returns the most specific type compatible with all given types.
+ * (i.e. most specific common super type)
+ * If no types is given, will return VoidBinding. If not compatible
+ * reference type is found, returns null.
+ */
+ private TypeBinding minimalErasedCandidate(TypeBinding[] types, List invocations) {
+ Map allInvocations = new HashMap(2);
+ int length = types.length;
+ int indexOfFirst = -1, actualLength = 0;
+ for (int i = 0; i < length; i++) {
+ TypeBinding type = types[i];
+ if (type == null) continue;
+ if (type.isBaseType()) return null;
+ if (indexOfFirst < 0) indexOfFirst = i;
+ actualLength ++;
+ }
+ switch (actualLength) {
+ case 0: return VoidBinding;
+ case 1: return types[indexOfFirst];
+ }
+
+ // record all supertypes of type
+ // intersect with all supertypes of otherType
+ TypeBinding firstType = types[indexOfFirst];
+ TypeBinding[] superTypes;
+ int superLength;
+ if (firstType.isBaseType()) {
+ return null;
+ } else if (firstType.isArrayType()) {
+ superLength = 4;
+ if (firstType.erasure() != firstType) {
+ ArrayList someInvocations = new ArrayList(1);
+ someInvocations.add(firstType);
+ allInvocations.put(firstType.erasure(), someInvocations);
+ }
+ superTypes = new TypeBinding[] {
+ firstType.erasure(),
+ getJavaIoSerializable(),
+ getJavaLangCloneable(),
+ getJavaLangObject(),
+ };
+ } else {
+ ArrayList typesToVisit = new ArrayList(5);
+ if (firstType.erasure() != firstType) {
+ ArrayList someInvocations = new ArrayList(1);
+ someInvocations.add(firstType);
+ allInvocations.put(firstType.erasure(), someInvocations);
+ }
+ typesToVisit.add(firstType.erasure());
+ ReferenceBinding currentType = (ReferenceBinding)firstType;
+ for (int i = 0, max = 1; i < max; i++) {
+ currentType = (ReferenceBinding) typesToVisit.get(i);
+ TypeBinding itsSuperclass = currentType.superclass();
+ if (itsSuperclass != null) {
+ TypeBinding itsSuperclassErasure = itsSuperclass.erasure();
+ if (!typesToVisit.contains(itsSuperclassErasure)) {
+ if (itsSuperclassErasure != itsSuperclass) {
+ ArrayList someInvocations = new ArrayList(1);
+ someInvocations.add(itsSuperclass);
+ allInvocations.put(itsSuperclassErasure, someInvocations);
+ }
+ typesToVisit.add(itsSuperclassErasure);
+ max++;
+ }
+ }
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ for (int j = 0, count = itsInterfaces.length; j < count; j++) {
+ TypeBinding itsInterface = itsInterfaces[j];
+ TypeBinding itsInterfaceErasure = itsInterface.erasure();
+ if (!typesToVisit.contains(itsInterfaceErasure)) {
+ if (itsInterfaceErasure != itsInterface) {
+ ArrayList someInvocations = new ArrayList(1);
+ someInvocations.add(itsInterface);
+ allInvocations.put(itsInterfaceErasure, someInvocations);
+ }
+ typesToVisit.add(itsInterfaceErasure);
+ max++;
+ }
+ }
+ }
+ superLength = typesToVisit.size();
+ superTypes = new TypeBinding[superLength];
+ typesToVisit.toArray(superTypes);
+ }
+ int remaining = superLength;
+ nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
+ TypeBinding otherType = types[i];
+ if (otherType == null)
+ continue nextOtherType;
+ else if (otherType.isArrayType()) {
+ nextSuperType: for (int j = 0; j < superLength; j++) {
+ TypeBinding superType = superTypes[j];
+ if (superType == null || superType == otherType) continue nextSuperType;
+ switch (superType.id) {
+ case T_JavaIoSerializable :
+ case T_JavaLangCloneable :
+ case T_JavaLangObject :
+ continue nextSuperType;
+ }
+ superTypes[j] = null;
+ if (--remaining == 0) return null;
+
+ }
+ continue nextOtherType;
+ }
+ ReferenceBinding otherRefType = (ReferenceBinding) otherType;
+ nextSuperType: for (int j = 0; j < superLength; j++) {
+ TypeBinding superType = superTypes[j];
+ if (superType == null) continue nextSuperType;
+ if (otherRefType.erasure().isCompatibleWith(superType)) {
+ TypeBinding match = otherRefType.findSuperTypeErasingTo((ReferenceBinding)superType);
+ if (match != null && match.erasure() != match) { // match can be null: interface.findSuperTypeErasingTo(Object)
+ ArrayList someInvocations = (ArrayList) allInvocations.get(superType);
+ if (someInvocations == null) someInvocations = new ArrayList(1);
+ someInvocations.add(match);
+ allInvocations.put(superType, someInvocations);
+ }
+ break nextSuperType;
+ } else {
+ superTypes[j] = null;
+ if (--remaining == 0) return null;
+ }
+ }
+ }
+ // per construction, first non-null supertype is most specific common supertype
+ for (int i = 0; i < superLength; i++) {
+ TypeBinding superType = superTypes[i];
+ if (superType != null) {
+ List matchingInvocations = (List)allInvocations.get(superType);
+ if (matchingInvocations != null) invocations.addAll(matchingInvocations);
+ return superType;
+ }
+ }
+ return null;
+ }
+
// Internal use only
/* All methods in visible are acceptable matches for the method in question...
* The methods defined by the receiver type appear before those defined by its
@@ -1861,29 +2774,28 @@ public abstract class Scope
* is defined by a superclass, when a lesser match is defined by the receiver type
* or a closer superclass.
*/
- protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
-
- MethodBinding method = null;
+ protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
+ MethodBinding problemMethod = null;
MethodBinding previous = null;
-
nextVisible : for (int i = 0; i < visibleSize; i++) {
- method = visible[i];
-
+ MethodBinding method = visible[i];
if (previous != null && method.declaringClass != previous.declaringClass)
break; // cannot answer a method farther up the hierarchy than the first method found
- if (!method.isStatic()) previous = method; // no ambiguity for static methods
+
+ if (!method.isStatic()) previous = method; // no ambiguity for static methods
for (int j = 0; j < visibleSize; j++) {
if (i == j) continue;
- MethodBinding next = visible[j];
- if (!areParametersAssignable(next.parameters, method.parameters))
+ if (!visible[j].areParametersCompatibleWith(method.parameters))
continue nextVisible;
}
compilationUnitScope().recordTypeReferences(method.thrownExceptions);
return method;
}
- return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+ if (problemMethod == null)
+ return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+ return problemMethod;
}
-
+
// Internal use only
/* All methods in visible are acceptable matches for the method in question...
* Since the receiver type is an interface, we ignore the possibility that 2 inherited
@@ -1913,42 +2825,53 @@ public abstract class Scope
public void foo(I i, X x) { i.bar(x); }
}
*/
- protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
- MethodBinding method = null;
+ protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
+ MethodBinding problemMethod = null;
nextVisible : for (int i = 0; i < visibleSize; i++) {
- method = visible[i];
+ MethodBinding method = visible[i];
for (int j = 0; j < visibleSize; j++) {
if (i == j) continue;
- MethodBinding next = visible[j];
- if (!areParametersAssignable(next.parameters, method.parameters))
+ if (!visible[j].areParametersCompatibleWith(method.parameters))
continue nextVisible;
}
compilationUnitScope().recordTypeReferences(method.thrownExceptions);
return method;
}
- return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+ if (problemMethod == null)
+ return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+ return problemMethod;
}
-
- // Internal use only
- /* All methods in visible are acceptable matches for the method in question...
- * Since 1.4, the inherited ambiguous case has been removed from mostSpecificClassMethodBinding
- */
- protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize) {
- MethodBinding method = null;
- nextVisible : for (int i = 0; i < visibleSize; i++) {
- method = visible[i];
- for (int j = 0; j < visibleSize; j++) {
- if (i == j) continue;
- MethodBinding next = visible[j];
- if (!areParametersAssignable(next.parameters, method.parameters))
- continue nextVisible;
+ protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
+ int[] compatibilityLevels = new int[visibleSize];
+ for (int i = 0; i < visibleSize; i++)
+ compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes);
+
+ for (int level = 0; level <= 2; level++) {
+ nextVisible : for (int i = 0; i < visibleSize; i++) {
+ if (compatibilityLevels[i] != level) continue nextVisible; // skip this method for now
+ MethodBinding method = visible[i];
+ for (int j = 0; j < visibleSize; j++) {
+ if (i == j || compatibilityLevels[j] != level) continue;
+ // tiebreak generic methods using variant where type params are substituted by their erasures
+ if (!visible[j].tiebreakMethod().areParametersCompatibleWith(method.tiebreakMethod().parameters)) {
+ if (method.isVarargs() && visible[j].isVarargs()) {
+ int paramLength = method.parameters.length;
+ if (paramLength == visible[j].parameters.length && paramLength == argumentTypes.length + 1) {
+ TypeBinding elementsType = ((ArrayBinding) visible[j].parameters[paramLength - 1]).elementsType();
+ if (method.parameters[paramLength - 1].isCompatibleWith(elementsType))
+ continue; // special case to choose between 2 varargs methods when the last arg is missing
+ }
+ }
+ continue nextVisible;
+ }
+ }
+ compilationUnitScope().recordTypeReferences(method.thrownExceptions);
+ return method;
}
- compilationUnitScope().recordTypeReferences(method.thrownExceptions);
- return method;
}
return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
- }
+ }
public final ClassScope outerMostClassScope() {
ClassScope lastClassScope = null;
@@ -1972,6 +2895,55 @@ public abstract class Scope
return lastMethodScope; // may answer null if no method around
}
+ protected int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
+ TypeBinding[] parameters = method.parameters;
+ int paramLength = parameters.length;
+ int argLength = arguments.length;
+ int lastIndex = argLength;
+ int level = COMPATIBLE; // no autoboxing or varargs support needed
+ if (method.isVarargs()) {
+ lastIndex = paramLength - 1;
+ if (paramLength == argLength) { // accept X or X[] but not X[][]
+ TypeBinding param = parameters[lastIndex]; // is an ArrayBinding by definition
+ TypeBinding arg = arguments[lastIndex];
+ if (param != arg && !arg.isCompatibleWith(param)) {
+ if (isBoxingCompatibleWith(arg, param)) {
+ level = AUTOBOX_COMPATIBLE; // autoboxing support needed
+ } else {
+ // expect X[], called with X
+ param = ((ArrayBinding) param).elementsType();
+ if (!arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
+ return NOT_COMPATIBLE;
+ level = VARARGS_COMPATIBLE; // varargs support needed
+ }
+ }
+ } else {
+ if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
+ TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
+ for (int i = lastIndex; i < argLength; i++) {
+ TypeBinding arg = arguments[i];
+ if (param != arg && !arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
+ return NOT_COMPATIBLE;
+ }
+ } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
+ return NOT_COMPATIBLE;
+ }
+ level = VARARGS_COMPATIBLE; // varargs support needed
+ }
+ // now compare standard arguments from 0 to lastIndex
+ }
+ for (int i = 0; i < lastIndex; i++) {
+ TypeBinding param = parameters[i];
+ TypeBinding arg = arguments[i];
+ if (arg != param && !arg.isCompatibleWith(param)) {
+ if (!isBoxingCompatibleWith(arg, param))
+ return NOT_COMPATIBLE;
+ level = AUTOBOX_COMPATIBLE; // autoboxing support needed
+ }
+ }
+ return level;
+ }
+
public abstract ProblemReporter problemReporter();
public final CompilationUnitDeclaration referenceCompilationUnit() {
@@ -1997,4 +2969,56 @@ public abstract class Scope
} while (scope != null);
return null;
}
+ /*
+ * Unboxing primitive
+ */
+ public int unboxing(int id) {
+ switch (id) {
+ case T_JavaLangInteger :
+ return T_int;
+ case T_JavaLangByte :
+ return T_byte;
+ case T_JavaLangShort :
+ return T_short;
+ case T_JavaLangCharacter :
+ return T_char;
+ case T_JavaLangLong :
+ return T_long;
+ case T_JavaLangFloat :
+ return T_float;
+ case T_JavaLangDouble :
+ return T_double;
+ case T_JavaLangBoolean :
+ return T_boolean;
+ case T_JavaLangVoid :
+ return T_void;
+ }
+ return id;
+ }
+ /*
+ * Unboxing primitive
+ */
+ public TypeBinding unboxing(TypeBinding type) {
+ switch (type.id) {
+ case T_JavaLangInteger :
+ return IntBinding;
+ case T_JavaLangByte :
+ return ByteBinding;
+ case T_JavaLangShort :
+ return ShortBinding;
+ case T_JavaLangCharacter :
+ return CharBinding;
+ case T_JavaLangLong :
+ return LongBinding;
+ case T_JavaLangFloat :
+ return FloatBinding;
+ case T_JavaLangDouble :
+ return DoubleBinding;
+ case T_JavaLangBoolean :
+ return BooleanBinding;
+ case T_JavaLangVoid :
+ return VoidBinding;
+ }
+ return type;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java b/src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
new file mode 100644
index 0000000..b4293a0
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/SignatureWrapper.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class SignatureWrapper {
+ public char[] signature;
+ public int start;
+ public int end;
+ public int bracket;
+
+ public SignatureWrapper(char[] signature) {
+ this.signature = signature;
+ this.start = 0;
+ this.end = this.bracket = -1;
+ }
+ public boolean atEnd() {
+ return this.start < 0 || this.start >= this.signature.length;
+ }
+ public int computeEnd() {
+ int index = this.start;
+ while (this.signature[index] == '[')
+ index++;
+ switch (this.signature[index]) {
+ case 'L' :
+ case 'T' :
+ this.end = CharOperation.indexOf(';', this.signature, this.start);
+ if (this.bracket <= this.start) // already know it if its > start
+ this.bracket = CharOperation.indexOf('<', this.signature, this.start);
+
+ if (this.bracket > this.start && this.bracket < this.end)
+ this.end = this.bracket;
+ else if (this.end == -1)
+ this.end = this.signature.length + 1;
+ break;
+ default :
+ this.end = this.start;
+ }
+
+ this.start = this.end + 1; // skip ';'
+ return this.end;
+ }
+ public char[] nextWord() {
+ this.end = CharOperation.indexOf(';', this.signature, this.start);
+ if (this.bracket <= this.start) // already know it if its > start
+ this.bracket = CharOperation.indexOf('<', this.signature, this.start);
+ int dot = CharOperation.indexOf('.', this.signature, this.start);
+
+ if (this.bracket > this.start && this.bracket < this.end)
+ this.end = this.bracket;
+ if (dot > this.start && dot < this.end)
+ this.end = dot;
+
+ return CharOperation.subarray(this.signature, this.start, this.start = this.end); // skip word
+ }
+ public String toString() {
+ return new String(this.signature) + " @ " + this.start; //$NON-NLS-1$
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index e791f1e..0702691 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -10,21 +10,23 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
-import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
public class SourceTypeBinding extends ReferenceBinding {
public ReferenceBinding superclass;
@@ -32,16 +34,17 @@ public class SourceTypeBinding extends ReferenceBinding {
public FieldBinding[] fields;
public MethodBinding[] methods;
public ReferenceBinding[] memberTypes;
+ public TypeVariableBinding[] typeVariables;
public ClassScope scope;
- // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
+ // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
public final static int METHOD_EMUL = 0;
public final static int FIELD_EMUL = 1;
public final static int CLASS_LITERAL_EMUL = 2;
public final static int RECEIVER_TYPE_EMUL = 3;
-
- Hashtable[] synthetics;
+ HashMap[] synthetics;
+ char[] genericReferenceTypeSignature;
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
this.compoundName = compoundName;
@@ -110,18 +113,18 @@ public void addDefaultAbstractMethods() {
* Answer the new field or the existing field if one already existed.
*/
-public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
+public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
+ synthetics[FIELD_EMUL] = new HashMap(5);
}
FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
if (synthField == null) {
synthField = new SyntheticFieldBinding(
- CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
+ CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name),
actualOuterLocalVariable.type,
AccPrivate | AccFinal | AccSynthetic,
this,
@@ -142,7 +145,7 @@ public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVaria
FieldDeclaration fieldDecl = typeDecl.fields[i];
if (fieldDecl.binding == existingField) {
synthField.name = CharOperation.concat(
- SyntheticArgumentBinding.OuterLocalPrefix,
+ TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
actualOuterLocalVariable.name,
("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
needRecheck = true;
@@ -157,20 +160,20 @@ public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVaria
* Answer the new field or the existing field if one already existed.
*/
-public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
+public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
+ synthetics[FIELD_EMUL] = new HashMap(5);
}
FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
if (synthField == null) {
synthField = new SyntheticFieldBinding(
CharOperation.concat(
- SyntheticArgumentBinding.EnclosingInstancePrefix,
+ TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
String.valueOf(enclosingType.depth()).toCharArray()),
enclosingType,
AccDefault | AccFinal | AccSynthetic,
@@ -197,20 +200,22 @@ public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
* Answer the new field or the existing field if one already existed.
*/
-public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
+public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[CLASS_LITERAL_EMUL] == null) {
- synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
+ synthetics[CLASS_LITERAL_EMUL] = new HashMap(5);
}
// use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
if (synthField == null) {
synthField = new SyntheticFieldBinding(
- ("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
+ CharOperation.concat(
+ TypeConstants.SYNTHETIC_CLASS,
+ String.valueOf(synthetics[CLASS_LITERAL_EMUL].size()).toCharArray()),
blockScope.getJavaLangClass(),
AccDefault | AccStatic | AccSynthetic,
this,
@@ -236,19 +241,19 @@ public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockSc
/* Add a new synthetic field for the emulation of the assert statement.
* Answer the new field or the existing field if one already existed.
*/
-public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScope blockScope) {
+public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[FIELD_EMUL] == null) {
- synthetics[FIELD_EMUL] = new Hashtable(5);
+ synthetics[FIELD_EMUL] = new HashMap(5);
}
FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
if (synthField == null) {
synthField = new SyntheticFieldBinding(
- "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+ TypeConstants.SYNTHETIC_ASSERT_DISABLED,
BooleanBinding,
AccDefault | AccStatic | AccSynthetic | AccFinal,
this,
@@ -269,7 +274,54 @@ public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScop
FieldDeclaration fieldDecl = typeDecl.fields[i];
if (fieldDecl.binding == existingField) {
synthField.name = CharOperation.concat(
- "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+ TypeConstants.SYNTHETIC_ASSERT_DISABLED,
+ ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
+ needRecheck = true;
+ break;
+ }
+ }
+ }
+ } while (needRecheck);
+ return synthField;
+}
+
+/* Add a new synthetic field for recording all enum constant values
+* Answer the new field or the existing field if one already existed.
+*/
+public FieldBinding addSyntheticFieldForEnumValues() {
+
+ if (synthetics == null) {
+ synthetics = new HashMap[4];
+ }
+ if (synthetics[FIELD_EMUL] == null) {
+ synthetics[FIELD_EMUL] = new HashMap(5);
+ }
+
+ FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$
+ if (synthField == null) {
+ synthField = new SyntheticFieldBinding(
+ TypeConstants.SYNTHETIC_ENUM_VALUES,
+ scope.createArrayType(this,1),
+ AccPrivate | AccStatic | AccSynthetic | AccFinal,
+ this,
+ Constant.NotAConstant,
+ synthetics[FIELD_EMUL].size());
+ synthetics[FIELD_EMUL].put("enumConstantValues", synthField); //$NON-NLS-1$
+ }
+ // ensure there is not already such a field defined by the user
+ // ensure there is not already such a field defined by the user
+ boolean needRecheck;
+ int index = 0;
+ do {
+ needRecheck = false;
+ FieldBinding existingField;
+ if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
+ TypeDeclaration typeDecl = scope.referenceContext;
+ for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
+ FieldDeclaration fieldDecl = typeDecl.fields[i];
+ if (fieldDecl.binding == existingField) {
+ synthField.name = CharOperation.concat(
+ TypeConstants.SYNTHETIC_ENUM_VALUES,
("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
needRecheck = true;
break;
@@ -284,64 +336,184 @@ public FieldBinding addSyntheticField(AssertStatement assertStatement, BlockScop
Answer the new method or the existing method if one already existed.
*/
-public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
+public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[METHOD_EMUL] == null) {
- synthetics[METHOD_EMUL] = new Hashtable(5);
+ synthetics[METHOD_EMUL] = new HashMap(5);
}
- SyntheticAccessMethodBinding accessMethod = null;
- SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
+ SyntheticMethodBinding accessMethod = null;
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
if (accessors == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
- synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
+ accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
+ synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]);
accessors[isReadAccess ? 0 : 1] = accessMethod;
} else {
if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
+ accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
accessors[isReadAccess ? 0 : 1] = accessMethod;
}
}
return accessMethod;
}
+/* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
+ * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
+*/
+
+public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
+
+ if (synthetics == null) {
+ synthetics = new HashMap[4];
+ }
+ if (synthetics[METHOD_EMUL] == null) {
+ synthetics[METHOD_EMUL] = new HashMap(5);
+ }
+
+ SyntheticMethodBinding accessMethod = null;
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(selector);
+ if (accessors == null) {
+ accessMethod = new SyntheticMethodBinding(this, selector);
+ synthetics[METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
+ accessors[0] = accessMethod;
+ } else {
+ if ((accessMethod = accessors[0]) == null) {
+ accessMethod = new SyntheticMethodBinding(this, selector);
+ accessors[0] = accessMethod;
+ }
+ }
+ return accessMethod;
+}
/* Add a new synthetic access method for access to .
* Must distinguish access method used for super access from others (need to use invokespecial bytecode)
Answer the new method or the existing method if one already existed.
*/
-public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
+public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
if (synthetics == null) {
- synthetics = new Hashtable[4];
+ synthetics = new HashMap[4];
}
if (synthetics[METHOD_EMUL] == null) {
- synthetics[METHOD_EMUL] = new Hashtable(5);
+ synthetics[METHOD_EMUL] = new HashMap(5);
}
- SyntheticAccessMethodBinding accessMethod = null;
- SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
+ SyntheticMethodBinding accessMethod = null;
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
if (accessors == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
- synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
+ accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
+ synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]);
accessors[isSuperAccess ? 0 : 1] = accessMethod;
} else {
if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
- accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
+ accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
accessors[isSuperAccess ? 0 : 1] = accessMethod;
}
}
return accessMethod;
}
+/*
+ * Record the fact that bridge methods need to be generated to override certain inherited methods
+ */
+public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding localTargetMethod) {
+ if (!isClass()) return null; // only classes get bridge methods
+ if (inheritedMethodToBridge.returnType.erasure() == localTargetMethod.returnType.erasure()
+ && inheritedMethodToBridge.areParameterErasuresEqual(localTargetMethod)) {
+ return null; // do not need bridge method
+ }
+ if (synthetics == null) {
+ synthetics = new HashMap[4];
+ }
+ if (synthetics[METHOD_EMUL] == null) {
+ synthetics[METHOD_EMUL] = new HashMap(5);
+ } else {
+ // check to see if there is another equivalent inheritedMethod already added
+ Iterator synthMethods = synthetics[METHOD_EMUL].keySet().iterator();
+ while (synthMethods.hasNext()) {
+ Object synthetic = synthMethods.next();
+ if (synthetic instanceof MethodBinding) {
+ MethodBinding method = (MethodBinding) synthetic;
+ if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
+ && inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
+ && inheritedMethodToBridge.areParameterErasuresEqual(method)) {
+ return null;
+ }
+ }
+ }
+ }
-public FieldBinding[] availableFields() {
- return fields();
+ SyntheticMethodBinding accessMethod = null;
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
+ if (accessors == null) {
+ accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
+ synthetics[METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
+ accessors[1] = accessMethod;
+ } else {
+ if ((accessMethod = accessors[1]) == null) {
+ accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, localTargetMethod);
+ accessors[1] = accessMethod;
+ }
+ }
+ return accessMethod;
}
-public MethodBinding[] availableMethods() {
- return methods();
+
+/**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+ if (otherType instanceof ReferenceBinding) {
+ TypeVariableBinding[] variables = this.typeVariables;
+ if (variables == NoTypeVariables) return;
+ // generic type is acting as parameterized type with its own parameters as arguments
+
+ // allow List to match with LinkedList
+ ReferenceBinding equivalent = this;
+ ReferenceBinding otherEquivalent = ((ReferenceBinding)otherType).findSuperTypeErasingTo(this);
+ if (otherEquivalent == null) {
+ // allow LinkedList to match List (downcast scenario)
+ equivalent = this.findSuperTypeErasingTo((ReferenceBinding)otherType.erasure());
+ if (equivalent == null) return;
+ otherEquivalent = (ReferenceBinding)otherType;
+ }
+ TypeBinding[] elements;
+ switch (equivalent.kind()) {
+ case Binding.GENERIC_TYPE :
+ elements = equivalent.typeVariables();
+ break;
+ case Binding.PARAMETERIZED_TYPE :
+ elements = ((ParameterizedTypeBinding)equivalent).arguments;
+ break;
+ default :
+ return;
+ }
+ TypeBinding[] otherElements;
+ switch (otherEquivalent.kind()) {
+ case Binding.GENERIC_TYPE :
+ otherElements = otherEquivalent.typeVariables();
+ break;
+ case Binding.PARAMETERIZED_TYPE :
+ otherElements = ((ParameterizedTypeBinding)otherEquivalent).arguments;
+ break;
+ case Binding.RAW_TYPE :
+ substitutes.clear(); // clear all variables to indicate raw generic method in the end
+ return;
+ default :
+ return;
+ }
+ for (int i = 0, length = elements.length; i < length; i++) {
+ elements[i].collectSubstitutes(otherElements[i], substitutes);
+ }
+ }
}
+
+public int kind() {
+ if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
+ return Binding.TYPE;
+}
+
void faultInTypesForFieldsAndMethods() {
fields();
methods();
@@ -349,48 +521,99 @@ void faultInTypesForFieldsAndMethods() {
for (int i = 0, length = memberTypes.length; i < length; i++)
((SourceTypeBinding) memberTypes[i]).faultInTypesForFieldsAndMethods();
}
-// NOTE: the type of each field of a source type is resolved when needed
+// NOTE: the type of each field of a source type is resolved when needed
public FieldBinding[] fields() {
-
+ int failed = 0;
try {
- int failed = 0;
- for (int f = 0, max = fields.length; f < max; f++) {
- if (resolveTypeFor(fields[f]) == null) {
- fields[f] = null;
+ for (int i = 0, length = fields.length; i < length; i++) {
+ if (resolveTypeFor(fields[i]) == null) {
+ fields[i] = null;
failed++;
}
}
+ } finally {
if (failed > 0) {
+ // ensure fields are consistent reqardless of the error
int newSize = fields.length - failed;
if (newSize == 0)
return fields = NoFields;
FieldBinding[] newFields = new FieldBinding[newSize];
- for (int i = 0, n = 0, max = fields.length; i < max; i++)
+ for (int i = 0, j = 0, length = fields.length; i < length; i++)
if (fields[i] != null)
- newFields[n++] = fields[i];
+ newFields[j++] = fields[i];
fields = newFields;
}
- } catch(AbortCompilation e){
- // ensure null fields are removed
- FieldBinding[] newFields = null;
- int count = 0;
- for (int i = 0, max = fields.length; i < max; i++){
- FieldBinding field = fields[i];
- if (field == null && newFields == null){
- System.arraycopy(fields, 0, newFields = new FieldBinding[max], 0, i);
- } else if (newFields != null && field != null) {
- newFields[count++] = field;
- }
- }
- if (newFields != null){
- System.arraycopy(newFields, 0, fields = new FieldBinding[count], 0, count);
- }
- throw e;
}
return fields;
}
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
+ */
+public char[] genericTypeSignature() {
+ if (this.genericReferenceTypeSignature == null) {
+ if (this.typeVariables == NoTypeVariables) {
+ this.genericReferenceTypeSignature = this.signature();
+ } else {
+ char[] typeSig = this.signature();
+ StringBuffer sig = new StringBuffer(10);
+ for (int i = 0; i < typeSig.length-1; i++) { // copy all but trailing semicolon
+ sig.append(typeSig[i]);
+ }
+ sig.append('<');
+ for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+ sig.append(this.typeVariables[i].genericTypeSignature());
+ }
+ sig.append(">;"); //$NON-NLS-1$
+ int sigLength = sig.length();
+ this.genericReferenceTypeSignature = new char[sigLength];
+ sig.getChars(0, sigLength, this.genericReferenceTypeSignature, 0);
+ }
+ }
+ return this.genericReferenceTypeSignature;
+}
+/**
+ * superclass superinterface1 ... superinterfaceN
+ * ;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
+ */
+public char[] genericSignature() {
+ StringBuffer sig = null;
+ if (this.typeVariables != NoTypeVariables) {
+ sig = new StringBuffer(10);
+ sig.append('<');
+ for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+ sig.append(this.typeVariables[i].genericSignature());
+ }
+ sig.append('>');
+ } else {
+ // could still need a signature if any of supertypes is parameterized
+ noSignature: if (this.superclass == null || !this.superclass.isParameterizedType()) {
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (this.superInterfaces[i].isParameterizedType()) break noSignature;
+ }
+ return null;
+ }
+ sig = new StringBuffer(10);
+ }
+ if (this.superclass != null) {
+ sig.append(this.superclass.genericTypeSignature());
+ } else {
+ // interface scenario only (as Object cannot be generic) - 65953
+ sig.append(scope.getJavaLangObject().genericTypeSignature());
+ }
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ sig.append(this.superInterfaces[i].genericTypeSignature());
+ }
+ return sig.toString().toCharArray();
+}
+public long getAnnotationTagBits() {
+ if ((this.tagBits & AnnotationResolved) == 0) {
+ TypeDeclaration typeDecl = this.scope.referenceContext;
+ typeDecl.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
+ }
+ return this.tagBits;
+}
public MethodBinding[] getDefaultAbstractMethods() {
int count = 0;
for (int i = methods.length; --i >= 0;)
@@ -413,7 +636,7 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
nextMethod : for (int m = methods.length; --m >= 0;) {
MethodBinding method = methods[m];
- if (method.selector == ConstructorDeclaration.ConstantPoolName && method.parameters.length == argCount) {
+ if (method.selector == TypeConstants.INIT && method.parameters.length == argCount) {
TypeBinding[] toMatch = method.parameters;
for (int p = 0; p < argCount; p++)
if (toMatch[p] != argumentTypes[p])
@@ -422,7 +645,7 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
}
}
} else {
- MethodBinding[] constructors = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
+ MethodBinding[] constructors = getMethods(TypeConstants.INIT); // takes care of duplicates & default abstract methods
nextConstructor : for (int c = constructors.length; --c >= 0;) {
MethodBinding constructor = constructors[c];
TypeBinding[] toMatch = constructor.parameters;
@@ -439,7 +662,8 @@ public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
// searches up the hierarchy as long as no potential (but not exact) match was found.
-public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
+ // sender from refScope calls recordTypeReference(this)
int argCount = argumentTypes.length;
int selectorLength = selector.length;
boolean foundNothing = true;
@@ -475,152 +699,86 @@ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes
if (foundNothing) {
if (isInterface()) {
- if (superInterfaces.length == 1)
- return superInterfaces[0].getExactMethod(selector, argumentTypes);
+ if (superInterfaces.length == 1) {
+ if (refScope != null)
+ refScope.recordTypeReference(superInterfaces[0]);
+ return superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
+ }
} else if (superclass != null) {
- return superclass.getExactMethod(selector, argumentTypes);
+ if (refScope != null)
+ refScope.recordTypeReference(superclass);
+ return superclass.getExactMethod(selector, argumentTypes, refScope);
}
}
return null;
}
-// NOTE: the type of a field of a source type is resolved when needed
+// NOTE: the type of a field of a source type is resolved when needed
public FieldBinding getField(char[] fieldName, boolean needResolve) {
// always resolve anyway on source types
int fieldLength = fieldName.length;
- for (int f = fields.length; --f >= 0;) {
- FieldBinding field = fields[f];
+ for (int i = 0, length = fields.length; i < length; i++) {
+ FieldBinding field = fields[i];
if (field.name.length == fieldLength && CharOperation.equals(field.name, fieldName)) {
- if (resolveTypeFor(field) != null)
- return field;
-
- int newSize = fields.length - 1;
- if (newSize == 0) {
- fields = NoFields;
- } else {
- FieldBinding[] newFields = new FieldBinding[newSize];
- System.arraycopy(fields, 0, newFields, 0, f);
- System.arraycopy(fields, f + 1, newFields, f, newSize - f);
- fields = newFields;
+ FieldBinding result = null;
+ try {
+ result = resolveTypeFor(field);
+ return result;
+ } finally {
+ if (result == null) {
+ // ensure fields are consistent reqardless of the error
+ int newSize = fields.length - 1;
+ if (newSize == 0) {
+ fields = NoFields;
+ } else {
+ FieldBinding[] newFields = new FieldBinding[newSize];
+ System.arraycopy(fields, 0, newFields, 0, i);
+ System.arraycopy(fields, i + 1, newFields, i, newSize - i);
+ fields = newFields;
+ }
+ }
}
- return null;
}
}
return null;
}
-// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
+// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding[] getMethods(char[] selector) {
- // handle forward references to potential default abstract methods
- addDefaultAbstractMethods();
-
- try{
- int count = 0;
- int lastIndex = -1;
- int selectorLength = selector.length;
- if ((modifiers & AccUnresolved) == 0) { // have resolved all arg types & return type of the methods
- for (int m = 0, length = methods.length; m < length; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- count++;
- lastIndex = m;
- }
- }
- } else {
- boolean foundProblem = false;
- int failed = 0;
- for (int m = 0, length = methods.length; m < length; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- if (resolveTypesFor(method) == null) {
- foundProblem = true;
- methods[m] = null; // unable to resolve parameters
- failed++;
- } else if (method.returnType == null) {
- foundProblem = true;
- } else {
- count++;
- lastIndex = m;
- }
- }
- }
-
- if (foundProblem || count > 1) {
- for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
- if (method != null && method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
- AbstractMethodDeclaration methodDecl = null;
- for (int i = 0; i < m; i++) {
- MethodBinding method2 = methods[i];
- if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
- if (method.areParametersEqual(method2)) {
- if (methodDecl == null) {
- methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
- scope.problemReporter().duplicateMethodInType(this, methodDecl);
- methodDecl.binding = null;
- methods[m] = null;
- failed++;
- }
- scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
- method2.sourceMethod().binding = null;
- methods[i] = null;
- failed++;
- }
- }
- }
- if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
- method.sourceMethod().binding = null;
- methods[m] = null;
- failed++;
- }
- }
- }
-
- if (failed > 0) {
- int newSize = methods.length - failed;
- if (newSize == 0)
- return methods = NoMethods;
-
- MethodBinding[] newMethods = new MethodBinding[newSize];
- for (int i = 0, n = 0, max = methods.length; i < max; i++)
- if (methods[i] != null)
- newMethods[n++] = methods[i];
- methods = newMethods;
- return getMethods(selector); // try again now that the problem methods have been removed
- }
- }
- }
- if (count == 1)
- return new MethodBinding[] {methods[lastIndex]};
- if (count > 1) {
- MethodBinding[] result = new MethodBinding[count];
- count = 0;
- for (int m = 0; m <= lastIndex; m++) {
- MethodBinding method = methods[m];
- if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
- result[count++] = method;
+ int selectorLength = selector.length;
+ boolean methodsAreResolved = (modifiers & AccUnresolved) == 0; // have resolved all arg types & return type of the methods
+ java.util.ArrayList matchingMethods = null;
+ for (int i = 0, length = methods.length; i < length; i++) {
+ MethodBinding method = methods[i];
+ if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+ if (!methodsAreResolved && resolveTypesFor(method) == null || method.returnType == null) {
+ methods();
+ return getMethods(selector); // try again since the problem methods have been removed
}
- return result;
+ if (matchingMethods == null)
+ matchingMethods = new java.util.ArrayList(2);
+ matchingMethods.add(method);
}
- } catch(AbortCompilation e){
- // ensure null methods are removed
- MethodBinding[] newMethods = null;
- int count = 0;
- for (int i = 0, max = methods.length; i < max; i++){
- MethodBinding method = methods[i];
- if (method == null && newMethods == null){
- System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
- } else if (newMethods != null && method != null) {
- newMethods[count++] = method;
+ }
+ if (matchingMethods == null) return NoMethods;
+
+ MethodBinding[] result = new MethodBinding[matchingMethods.size()];
+ matchingMethods.toArray(result);
+ if (!methodsAreResolved) {
+ for (int i = 0, length = result.length - 1; i < length; i++) {
+ MethodBinding method = result[i];
+ for (int j = length; j > i; j--) {
+ boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
+ ? method.areParameterErasuresEqual(result[j])
+ : method.areParametersEqual(result[j]);
+ if (paramsMatch) {
+ methods();
+ return getMethods(selector); // try again since the duplicate methods have been removed
+ }
}
}
- if (newMethods != null){
- System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
- }
- modifiers ^= AccUnresolved;
- throw e;
- }
- return NoMethods;
+ }
+ return result;
}
/* Answer the synthetic field for
* or null if one does not exist.
@@ -631,16 +789,72 @@ public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVaria
if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
}
+/*
+ * Answer the bridge method associated for an inherited methods or null if one does not exist
+ */
+public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
+
+ if (synthetics == null) return null;
+ if (synthetics[METHOD_EMUL] == null) return null;
+ SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(inheritedMethodToBridge);
+ if (accessors == null) return null;
+ return accessors[1];
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+
+ if (this == otherType) return true;
+ if (otherType == null) return false;
+ switch(otherType.kind()) {
+
+ case Binding.WILDCARD_TYPE :
+ return ((WildcardBinding) otherType).boundCheck(this);
+
+ case Binding.PARAMETERIZED_TYPE :
+ if ((otherType.tagBits & HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
+ return false; // should have been identical
+ ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
+ if (this != otherParamType.type)
+ return false;
+ if (!isStatic()) { // static member types do not compare their enclosing
+ ReferenceBinding enclosing = enclosingType();
+ if (enclosing != null && !enclosing.isEquivalentTo(otherParamType.enclosingType()))
+ return false;
+ }
+ int length = this.typeVariables == null ? 0 : this.typeVariables.length;
+ TypeBinding[] otherArguments = otherParamType.arguments;
+ int otherLength = otherArguments == null ? 0 : otherArguments.length;
+ if (otherLength != length)
+ return false;
+ for (int i = 0; i < length; i++) {
+ if (!this.typeVariables[i].isTypeArgumentContainedBy(otherArguments[i]))
+ return false;
+ }
+ return true;
+
+ case Binding.RAW_TYPE :
+ return otherType.erasure() == this;
+ }
+ return false;
+}
+
+public boolean isGenericType() {
+ return this.typeVariables != NoTypeVariables;
+}
+
public ReferenceBinding[] memberTypes() {
return this.memberTypes;
}
public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
if (this.synthetics == null) {
- this.synthetics = new Hashtable[4];
+ this.synthetics = new HashMap[4];
}
if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
- this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+ this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
}
Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
@@ -659,10 +873,10 @@ public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBi
public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
if (this.synthetics == null) {
- this.synthetics = new Hashtable[4];
+ this.synthetics = new HashMap[4];
}
if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
- this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+ this.synthetics[RECEIVER_TYPE_EMUL] = new HashMap(5);
}
@@ -683,82 +897,83 @@ public boolean hasMemberTypes() {
}
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding[] methods() {
+ if ((modifiers & AccUnresolved) == 0)
+ return methods;
+
+ int failed = 0;
try {
- if ((modifiers & AccUnresolved) == 0)
- return methods;
-
- int failed = 0;
- for (int m = 0, max = methods.length; m < max; m++) {
- if (resolveTypesFor(methods[m]) == null) {
- methods[m] = null; // unable to resolve parameters
+ for (int i = 0, length = methods.length; i < length; i++) {
+ if (resolveTypesFor(methods[i]) == null) {
+ methods[i] = null; // unable to resolve parameters
failed++;
}
}
-
- for (int m = methods.length; --m >= 0;) {
- MethodBinding method = methods[m];
+
+ // find & report collision cases
+ for (int i = 0, length = methods.length; i < length; i++) {
+ MethodBinding method = methods[i];
if (method != null) {
AbstractMethodDeclaration methodDecl = null;
- for (int i = 0; i < m; i++) {
- MethodBinding method2 = methods[i];
+ for (int j = length - 1; j > i; j--) {
+ MethodBinding method2 = methods[j];
if (method2 != null && CharOperation.equals(method.selector, method2.selector)) {
- if (method.areParametersEqual(method2)) {
+ boolean paramsMatch = fPackage.environment.options.sourceLevel >= ClassFileConstants.JDK1_5
+ ? method.areParameterErasuresEqual(method2)
+ : method.areParametersEqual(method2);
+ if (paramsMatch) {
+ boolean isEnumSpecialMethod = isEnum()
+ && (method.selector == TypeConstants.VALUEOF || method.selector == TypeConstants.VALUES);
if (methodDecl == null) {
- methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost
- scope.problemReporter().duplicateMethodInType(this, methodDecl);
- methodDecl.binding = null;
- methods[m] = null;
+ methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
+ if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
+ if (isEnumSpecialMethod)
+ scope.problemReporter().duplicateEnumSpecialMethod(this, methodDecl);
+ else
+ scope.problemReporter().duplicateMethodInType(this, methodDecl);
+ methodDecl.binding = null;
+ methods[i] = null;
+ failed++;
+ }
+ }
+ AbstractMethodDeclaration method2Decl = method2.sourceMethod();
+ if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
+ if (isEnumSpecialMethod)
+ scope.problemReporter().duplicateEnumSpecialMethod(this, method2Decl);
+ else
+ scope.problemReporter().duplicateMethodInType(this, method2Decl);
+ method2Decl.binding = null;
+ methods[j] = null;
failed++;
}
- scope.problemReporter().duplicateMethodInType(this, method2.sourceMethod());
- method2.sourceMethod().binding = null;
- methods[i] = null;
- failed++;
}
}
}
if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
method.sourceMethod().binding = null;
- methods[m] = null;
+ methods[i] = null;
failed++;
}
}
}
-
+ } finally {
if (failed > 0) {
int newSize = methods.length - failed;
if (newSize == 0) {
methods = NoMethods;
} else {
MethodBinding[] newMethods = new MethodBinding[newSize];
- for (int m = 0, n = 0, max = methods.length; m < max; m++)
- if (methods[m] != null)
- newMethods[n++] = methods[m];
+ for (int i = 0, j = 0, length = methods.length; i < length; i++)
+ if (methods[i] != null)
+ newMethods[j++] = methods[i];
methods = newMethods;
}
}
-
+
// handle forward references to potential default abstract methods
addDefaultAbstractMethods();
- } catch(AbortCompilation e){
- // ensure null methods are removed
- MethodBinding[] newMethods = null;
- int count = 0;
- for (int i = 0, max = methods.length; i < max; i++){
- MethodBinding method = methods[i];
- if (method == null && newMethods == null){
- System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
- } else if (newMethods != null && method != null) {
- newMethods[count++] = method;
- }
- }
- if (newMethods != null){
- System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
- }
- modifiers ^= AccUnresolved;
- throw e;
+
+ modifiers &= ~AccUnresolved;
}
- modifiers ^= AccUnresolved;
return methods;
}
private FieldBinding resolveTypeFor(FieldBinding field) {
@@ -770,33 +985,59 @@ private FieldBinding resolveTypeFor(FieldBinding field) {
if (fieldDecls[f].binding != field)
continue;
- field.type = fieldDecls[f].getTypeBinding(scope);
- field.modifiers ^= AccUnresolved;
- if (!field.type.isValidBinding()) {
- scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
- //scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
- fieldDecls[f].binding = null;
- return null;
- }
- if (field.type == VoidBinding) {
- scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
- fieldDecls[f].binding = null;
- return null;
- }
- if (field.type.isArrayType() && ((ArrayBinding) field.type).leafComponentType == VoidBinding) {
- scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
- fieldDecls[f].binding = null;
- return null;
- }
+ MethodScope initializationScope = field.isStatic()
+ ? scope.referenceContext.staticInitializerScope
+ : scope.referenceContext.initializerScope;
+ FieldBinding previousField = initializationScope.initializedField;
+ try {
+ initializationScope.initializedField = field;
+ FieldDeclaration fieldDecl = fieldDecls[f];
+ TypeBinding fieldType =
+ fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
+ ? this // enum constant is implicitly of declaring enum type
+ : fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
+ field.type = fieldType;
+ field.modifiers &= ~AccUnresolved;
+ if (fieldType == null) {
+ fieldDecls[f].binding = null;
+ return null;
+ }
+ if (fieldType == VoidBinding) {
+ scope.problemReporter().variableTypeCannotBeVoid(fieldDecls[f]);
+ fieldDecls[f].binding = null;
+ return null;
+ }
+ if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == VoidBinding) {
+ scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecls[f]);
+ fieldDecls[f].binding = null;
+ return null;
+ }
+ if (fieldType instanceof ReferenceBinding && (((ReferenceBinding)fieldType).modifiers & AccGenericSignature) != 0) {
+ field.modifiers |= AccGenericSignature;
+ }
+ } finally {
+ initializationScope.initializedField = previousField;
+ }
return field;
}
return null; // should never reach this point
}
private MethodBinding resolveTypesFor(MethodBinding method) {
+
if ((method.modifiers & AccUnresolved) == 0)
return method;
AbstractMethodDeclaration methodDecl = method.sourceMethod();
+ if (methodDecl == null) return null; // method could not be resolved in previous iteration
+
+ TypeParameter[] typeParameters = methodDecl.typeParameters();
+ if (typeParameters != null) {
+ methodDecl.scope.connectTypeVariables(typeParameters);
+ // Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
+ for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
+ typeParameters[i].checkBounds(methodDecl.scope);
+ }
+ }
TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
if (exceptionTypes != null) {
int size = exceptionTypes.length;
@@ -805,16 +1046,21 @@ private MethodBinding resolveTypesFor(MethodBinding method) {
int count = 0;
ReferenceBinding resolvedExceptionType;
for (int i = 0; i < size; i++) {
- resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].getTypeBinding(scope);
- if (!resolvedExceptionType.isValidBinding()) {
- methodDecl.scope.problemReporter().exceptionTypeProblem(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
- //methodDecl.scope.problemReporter().invalidType(exceptionTypes[i], resolvedExceptionType);
+ resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
+ if (resolvedExceptionType == null) {
+ continue;
+ }
+ if (resolvedExceptionType.isGenericType() || resolvedExceptionType.isParameterizedType()) {
+ methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
continue;
}
if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
continue;
}
+ if ((resolvedExceptionType.modifiers & AccGenericSignature) != 0) {
+ method.modifiers |= AccGenericSignature;
+ }
method.thrownExceptions[count++] = resolvedExceptionType;
}
if (count < size)
@@ -828,50 +1074,63 @@ private MethodBinding resolveTypesFor(MethodBinding method) {
method.parameters = new TypeBinding[size];
for (int i = 0; i < size; i++) {
Argument arg = arguments[i];
- method.parameters[i] = arg.type.getTypeBinding(scope);
- if (!method.parameters[i].isValidBinding()) {
- methodDecl.scope.problemReporter().argumentTypeProblem(this, methodDecl, arg, method.parameters[i]);
- //methodDecl.scope.problemReporter().invalidType(arg, method.parameters[i]);
+ TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
+ if (parameterType == null) {
foundArgProblem = true;
- } else if (method.parameters[i] == VoidBinding) {
+ } else if (parameterType == VoidBinding) {
methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
foundArgProblem = true;
- } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
+ } else if (parameterType.isArrayType() && ((ArrayBinding) parameterType).leafComponentType == VoidBinding) {
methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
foundArgProblem = true;
+ } else {
+ if (parameterType instanceof ReferenceBinding && (((ReferenceBinding)parameterType).modifiers & AccGenericSignature) != 0) {
+ method.modifiers |= AccGenericSignature;
+ }
+ method.parameters[i] = parameterType;
}
}
}
boolean foundReturnTypeProblem = false;
if (!method.isConstructor()) {
- TypeReference returnType = ((MethodDeclaration) methodDecl).returnType;
+ TypeReference returnType = methodDecl instanceof MethodDeclaration
+ ? ((MethodDeclaration) methodDecl).returnType
+ : ((AnnotationMethodDeclaration) methodDecl).returnType;
if (returnType == null) {
methodDecl.scope.problemReporter().missingReturnType(methodDecl);
method.returnType = null;
foundReturnTypeProblem = true;
} else {
- method.returnType = returnType.getTypeBinding(scope);
- if (!method.returnType.isValidBinding()) {
- methodDecl.scope.problemReporter().returnTypeProblem(this, (MethodDeclaration) methodDecl, method.returnType);
- //methodDecl.scope.problemReporter().invalidType(returnType, method.returnType);
- method.returnType = null;
+ TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/);
+ if (methodType == null) {
foundReturnTypeProblem = true;
- } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
+ } else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == VoidBinding) {
methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
- method.returnType = null;
foundReturnTypeProblem = true;
+ } else {
+ method.returnType = methodType;
+ if (methodType instanceof ReferenceBinding && (((ReferenceBinding)methodType).modifiers & AccGenericSignature) != 0) {
+ method.modifiers |= AccGenericSignature;
+ }
}
}
}
if (foundArgProblem) {
methodDecl.binding = null;
+ // nullify type parameter bindings as well as they have a backpointer to the method binding
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
+ if (typeParameters != null)
+ for (int i = 0, length = typeParameters.length; i < length; i++) {
+ TypeParameter parameter = typeParameters[i];
+ parameter.binding = null;
+ }
return null;
}
if (foundReturnTypeProblem)
return method; // but its still unresolved with a null return type & is still connected to its method declaration
- method.modifiers ^= AccUnresolved;
+ method.modifiers &= ~AccUnresolved;
return method;
}
public final int sourceEnd() {
@@ -886,39 +1145,40 @@ public ReferenceBinding superclass() {
public ReferenceBinding[] superInterfaces() {
return superInterfaces;
}
-public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
+// TODO (philippe) could be a performance issue since some senders are building the list just to count them
+public SyntheticMethodBinding[] syntheticMethods() {
if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
// difficult to compute size up front because of the embedded arrays so assume there is only 1
int index = 0;
- SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
- Enumeration fieldsOrMethods = synthetics[METHOD_EMUL].keys();
- while (fieldsOrMethods.hasMoreElements()) {
+ SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
+ Iterator fieldsOrMethods = synthetics[METHOD_EMUL].keySet().iterator();
+ while (fieldsOrMethods.hasNext()) {
- Object fieldOrMethod = fieldsOrMethods.nextElement();
+ Object fieldOrMethod = fieldsOrMethods.next();
if (fieldOrMethod instanceof MethodBinding) {
- SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
+ SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
int numberOfAccessors = 0;
if (methodAccessors[0] != null) numberOfAccessors++;
if (methodAccessors[1] != null) numberOfAccessors++;
if (index + numberOfAccessors > bindings.length)
- System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
+ System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
if (methodAccessors[0] != null)
bindings[index++] = methodAccessors[0]; // super access
if (methodAccessors[1] != null)
- bindings[index++] = methodAccessors[1]; // normal access
+ bindings[index++] = methodAccessors[1]; // normal access or bridge
} else {
- SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
+ SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
int numberOfAccessors = 0;
if (fieldAccessors[0] != null) numberOfAccessors++;
if (fieldAccessors[1] != null) numberOfAccessors++;
if (index + numberOfAccessors > bindings.length)
- System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + numberOfAccessors]), 0, index);
+ System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
if (fieldAccessors[0] != null)
bindings[index++] = fieldAccessors[0]; // read access
if (fieldAccessors[1] != null)
@@ -928,9 +1188,9 @@ public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
// sort them in according to their own indexes
int length;
- SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
+ SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
for (int i = 0; i < length; i++){
- SyntheticAccessMethodBinding binding = bindings[i];
+ SyntheticMethodBinding binding = bindings[i];
sortedBindings[binding.index] = binding;
}
return sortedBindings;
@@ -950,89 +1210,108 @@ public FieldBinding[] syntheticFields() {
// add innerclass synthetics
if (synthetics[FIELD_EMUL] != null){
- Enumeration elements = synthetics[FIELD_EMUL].elements();
+ Iterator elements = synthetics[FIELD_EMUL].values().iterator();
for (int i = 0; i < fieldSize; i++) {
- SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+ SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
bindings[synthBinding.index] = synthBinding;
}
}
// add class literal synthetics
if (synthetics[CLASS_LITERAL_EMUL] != null){
- Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
+ Iterator elements = synthetics[CLASS_LITERAL_EMUL].values().iterator();
for (int i = 0; i < literalSize; i++) {
- SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+ SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
bindings[fieldSize+synthBinding.index] = synthBinding;
}
}
return bindings;
}
public String toString() {
- String s = "(id="+(id == NoId ? "NoId" : (""+id) ) +")\n"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-4$ //$NON-NLS-1$
-
- if (isDeprecated()) s += "deprecated "; //$NON-NLS-1$
- if (isPublic()) s += "public "; //$NON-NLS-1$
- if (isProtected()) s += "protected "; //$NON-NLS-1$
- if (isPrivate()) s += "private "; //$NON-NLS-1$
- if (isAbstract() && isClass()) s += "abstract "; //$NON-NLS-1$
- if (isStatic() && isNestedType()) s += "static "; //$NON-NLS-1$
- if (isFinal()) s += "final "; //$NON-NLS-1$
-
- s += isInterface() ? "interface " : "class "; //$NON-NLS-1$ //$NON-NLS-2$
- s += (compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"; //$NON-NLS-1$
-
- s += "\n\textends "; //$NON-NLS-1$
- s += (superclass != null) ? superclass.debugName() : "NULL TYPE"; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer(30);
+ buffer.append("(id="); //$NON-NLS-1$
+ if (id == NoId)
+ buffer.append("NoId"); //$NON-NLS-1$
+ else
+ buffer.append(id);
+ buffer.append(")\n"); //$NON-NLS-1$
+ if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
+ if (isPublic()) buffer.append("public "); //$NON-NLS-1$
+ if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
+ if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
+ if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
+ if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
+ if (isFinal()) buffer.append("final "); //$NON-NLS-1$
+
+ buffer.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$
+
+ if (this.typeVariables != null && this.typeVariables != NoTypeVariables) {
+ buffer.append("\n\t<"); //$NON-NLS-1$
+ for (int i = 0, length = this.typeVariables.length; i < length; i++) {
+ if (i > 0)
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append((this.typeVariables[i] != null) ? this.typeVariables[i].toString() : "NULL TYPE VARIABLE"); //$NON-NLS-1$
+ }
+ buffer.append(">"); //$NON-NLS-1$
+ } else {
+ buffer.append(""); //$NON-NLS-1$
+ }
+ buffer.append("\n\textends "); //$NON-NLS-1$
+ buffer.append((superclass != null) ? superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$
if (superInterfaces != null) {
if (superInterfaces != NoSuperInterfaces) {
- s += "\n\timplements : "; //$NON-NLS-1$
+ buffer.append("\n\timplements : "); //$NON-NLS-1$
for (int i = 0, length = superInterfaces.length; i < length; i++) {
if (i > 0)
- s += ", "; //$NON-NLS-1$
- s += (superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append((superInterfaces[i] != null) ? superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
}
}
} else {
- s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
+ buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
}
if (enclosingType() != null) {
- s += "\n\tenclosing type : "; //$NON-NLS-1$
- s += enclosingType().debugName();
+ buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
+ buffer.append(enclosingType().debugName());
}
if (fields != null) {
if (fields != NoFields) {
- s += "\n/* fields */"; //$NON-NLS-1$
+ buffer.append("\n/* fields */"); //$NON-NLS-1$
for (int i = 0, length = fields.length; i < length; i++)
- s += (fields[i] != null) ? "\n" + fields[i].toString() : "\nNULL FIELD"; //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append('\n').append((fields[i] != null) ? fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
}
} else {
- s += "NULL FIELDS"; //$NON-NLS-1$
+ buffer.append("NULL FIELDS"); //$NON-NLS-1$
}
if (methods != null) {
if (methods != NoMethods) {
- s += "\n/* methods */"; //$NON-NLS-1$
+ buffer.append("\n/* methods */"); //$NON-NLS-1$
for (int i = 0, length = methods.length; i < length; i++)
- s += (methods[i] != null) ? "\n" + methods[i].toString() : "\nNULL METHOD"; //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append('\n').append((methods[i] != null) ? methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
}
} else {
- s += "NULL METHODS"; //$NON-NLS-1$
+ buffer.append("NULL METHODS"); //$NON-NLS-1$
}
if (memberTypes != null) {
if (memberTypes != NoMemberTypes) {
- s += "\n/* members */"; //$NON-NLS-1$
+ buffer.append("\n/* members */"); //$NON-NLS-1$
for (int i = 0, length = memberTypes.length; i < length; i++)
- s += (memberTypes[i] != null) ? "\n" + memberTypes[i].toString() : "\nNULL TYPE"; //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append('\n').append((memberTypes[i] != null) ? memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
}
} else {
- s += "NULL MEMBER TYPES"; //$NON-NLS-1$
+ buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
}
- s += "\n\n\n"; //$NON-NLS-1$
- return s;
+ buffer.append("\n\n"); //$NON-NLS-1$
+ return buffer.toString();
+}
+public TypeVariableBinding[] typeVariables() {
+ return this.typeVariables;
}
void verifyMethods(MethodVerifier verifier) {
verifier.verify(this);
@@ -1055,11 +1334,11 @@ public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, bool
// class T { class M{}}
// class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
if (!onlyExactMatch){
- Enumeration accessFields = synthetics[FIELD_EMUL].elements();
- while (accessFields.hasMoreElements()) {
- field = (FieldBinding) accessFields.nextElement();
- if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
- && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
+ Iterator accessFields = synthetics[FIELD_EMUL].values().iterator();
+ while (accessFields.hasNext()) {
+ field = (FieldBinding) accessFields.next();
+ if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name)
+ && ((ReferenceBinding) field.type).findSuperTypeErasingTo(targetEnclosingType) != null)
return field;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java b/src/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
similarity index 69%
rename from src/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java
rename to src/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
index 9f2e688..8d40cd0 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/Substitution.java
@@ -10,12 +10,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
-public interface BindingIds {
- final int FIELD = 1;
- final int LOCAL = 2;
- final int VARIABLE = FIELD | LOCAL;
- final int TYPE = 4;
- final int METHOD = 8;
- final int PACKAGE = 16;
- final int IMPORT = 32;
+/*
+ * Encapsulates aspects related to type variable substitution
+ */
+public interface Substitution {
+
+ /**
+ * Returns the type substitute for a given type, or itself
+ * if no substitution got performed.
+ */
+ TypeBinding substitute(TypeBinding originalType);
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
index 521c6ea..7c08f8e 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
@@ -34,14 +34,11 @@ public class SyntheticArgumentBinding extends LocalVariableBinding {
public LocalVariableBinding actualOuterLocalVariable;
// if the argument has a matching synthetic field
public FieldBinding matchingField;
-
- final static char[] OuterLocalPrefix = { 'v', 'a', 'l', '$' };
- final static char[] EnclosingInstancePrefix = { 't', 'h', 'i', 's', '$' };
public SyntheticArgumentBinding(LocalVariableBinding actualOuterLocalVariable) {
super(
- CharOperation.concat(OuterLocalPrefix, actualOuterLocalVariable.name),
+ CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name),
actualOuterLocalVariable.type,
AccFinal,
true);
@@ -52,7 +49,7 @@ public class SyntheticArgumentBinding extends LocalVariableBinding {
super(
CharOperation.concat(
- SyntheticArgumentBinding.EnclosingInstancePrefix,
+ TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
String.valueOf(enclosingType.depth()).toCharArray()),
enclosingType,
AccFinal,
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
similarity index 69%
rename from src/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
rename to src/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 0803da4..f256cdd 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -14,33 +14,34 @@ import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-public class SyntheticAccessMethodBinding extends MethodBinding {
+public class SyntheticMethodBinding extends MethodBinding {
public FieldBinding targetReadField; // read access to a field
public FieldBinding targetWriteField; // write access to a field
public MethodBinding targetMethod; // method or constructor
- public int accessType;
+ public int kind;
public final static int FieldReadAccess = 1; // field read
public final static int FieldWriteAccess = 2; // field write
public final static int MethodAccess = 3; // normal method
public final static int ConstructorAccess = 4; // constructor
public final static int SuperMethodAccess = 5; // super method
-
- final static char[] AccessMethodPrefix = { 'a', 'c', 'c', 'e', 's', 's', '$' };
+ public final static int BridgeMethod = 6; // bridge method
+ public final static int EnumValues = 7; // enum #values()
+ public final static int EnumValueOf = 8; // enum #valueOf(String)
public int sourceStart = 0; // start position of the matching declaration
public int index; // used for sorting access methods in the class file
- public SyntheticAccessMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) {
+ public SyntheticMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) {
this.modifiers = AccDefault | AccStatic | AccSynthetic;
SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
- SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+ SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods();
int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
this.index = methodId;
- this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+ this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray());
if (isReadAccess) {
this.returnType = targetField.type;
if (targetField.isStatic()) {
@@ -50,7 +51,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
this.parameters[0] = declaringSourceType;
}
this.targetReadField = targetField;
- this.accessType = FieldReadAccess;
+ this.kind = FieldReadAccess;
} else {
this.returnType = VoidBinding;
if (targetField.isStatic()) {
@@ -62,7 +63,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
this.parameters[1] = targetField.type;
}
this.targetWriteField = targetField;
- this.accessType = FieldWriteAccess;
+ this.kind = FieldWriteAccess;
}
this.thrownExceptions = NoExceptions;
this.declaringClass = declaringSourceType;
@@ -92,7 +93,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
}
}
if (needRename) { // retry with a selector postfixed by a growing methodId
- this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+ this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray()));
}
} while (needRename);
@@ -126,7 +127,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead
}
- public SyntheticAccessMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
+ public SyntheticMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
if (targetMethod.isConstructor()) {
this.initializeConstructorAccessor(targetMethod);
@@ -136,6 +137,54 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
}
/**
+ * Construct a bridge method
+ */
+ public SyntheticMethodBinding(MethodBinding overridenMethodToBridge, MethodBinding localTargetMethod) {
+
+ this.declaringClass = localTargetMethod.declaringClass;
+ this.selector = overridenMethodToBridge.selector;
+ this.modifiers = overridenMethodToBridge.modifiers | AccBridge | AccSynthetic;
+ this.modifiers &= ~(AccAbstract | AccNative);
+ this.returnType = overridenMethodToBridge.returnType;
+ this.parameters = overridenMethodToBridge.parameters;
+ this.thrownExceptions = overridenMethodToBridge.thrownExceptions;
+ this.targetMethod = localTargetMethod;
+ this.kind = BridgeMethod;
+ SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+ int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+ this.index = methodId;
+ }
+
+ /**
+ * Construct enum special methods: values or valueOf methods
+ */
+ public SyntheticMethodBinding(SourceTypeBinding declaringEnum, char[] selector) {
+ if (selector == TypeConstants.VALUES) {
+ this.declaringClass = declaringEnum;
+ this.selector = selector;
+ this.modifiers = AccFinal | AccPublic | AccStatic;
+ this.returnType = declaringEnum.scope.createArrayType(declaringEnum, 1);
+ this.parameters = NoParameters;
+ this.thrownExceptions = NoExceptions;
+ this.kind = EnumValues;
+ SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+ int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+ this.index = methodId;
+ } else if (selector == TypeConstants.VALUEOF) {
+ this.declaringClass = declaringEnum;
+ this.selector = selector;
+ this.modifiers = AccFinal | AccPublic | AccStatic;
+ this.returnType = declaringEnum;
+ this.parameters = new TypeBinding[]{ declaringEnum.scope.getJavaLangString() };
+ this.thrownExceptions = NoExceptions;
+ this.kind = EnumValueOf;
+ SyntheticMethodBinding[] knownAccessMethods = ((SourceTypeBinding)this.declaringClass).syntheticMethods();
+ int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+ this.index = methodId;
+ }
+ }
+
+ /**
* An constructor accessor is a constructor with an extra argument (declaringClass), in case of
* collision with an existing constructor, then add again an extra argument (declaringClass again).
*/
@@ -144,13 +193,13 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
this.targetMethod = accessedConstructor;
this.modifiers = AccDefault | AccSynthetic;
SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass;
- SyntheticAccessMethodBinding[] knownAccessMethods =
- sourceType.syntheticAccessMethods();
- this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+ SyntheticMethodBinding[] knownSyntheticMethods =
+ sourceType.syntheticMethods();
+ this.index = knownSyntheticMethods == null ? 0 : knownSyntheticMethods.length;
this.selector = accessedConstructor.selector;
this.returnType = accessedConstructor.returnType;
- this.accessType = ConstructorAccess;
+ this.kind = ConstructorAccess;
this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1];
System.arraycopy(
accessedConstructor.parameters,
@@ -178,12 +227,12 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
}
}
// check for collision with synthetic accessors
- if (knownAccessMethods != null) {
- for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
- if (knownAccessMethods[i] == null)
+ if (knownSyntheticMethods != null) {
+ for (int i = 0, length = knownSyntheticMethods.length; i < length; i++) {
+ if (knownSyntheticMethods[i] == null)
continue;
- if (CharOperation.equals(this.selector, knownAccessMethods[i].selector)
- && this.areParametersEqual(knownAccessMethods[i])) {
+ if (CharOperation.equals(this.selector, knownSyntheticMethods[i].selector)
+ && this.areParametersEqual(knownSyntheticMethods[i])) {
needRename = true;
break check;
}
@@ -223,13 +272,13 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
this.targetMethod = accessedMethod;
this.modifiers = AccDefault | AccStatic | AccSynthetic;
SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType;
- SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+ SyntheticMethodBinding[] knownAccessMethods = declaringSourceType.syntheticMethods();
int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
this.index = methodId;
- this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+ this.selector = CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(methodId).toCharArray());
this.returnType = accessedMethod.returnType;
- this.accessType = isSuperAccess ? SuperMethodAccess : MethodAccess;
+ this.kind = isSuperAccess ? SuperMethodAccess : MethodAccess;
if (accessedMethod.isStatic()) {
this.parameters = accessedMethod.parameters;
@@ -266,7 +315,7 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
}
}
if (needRename) { // retry with a selector & a growing methodId
- this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+ this.setSelector(CharOperation.concat(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX, String.valueOf(++methodId).toCharArray()));
}
} while (needRename);
@@ -283,6 +332,6 @@ public class SyntheticAccessMethodBinding extends MethodBinding {
}
protected boolean isConstructorRelated() {
- return accessType == ConstructorAccess;
+ return kind == ConstructorAccess;
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/src/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index 556a7c4..ffc6b55 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -10,36 +10,86 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
public interface TagBits {
+
// Tag bits in the tagBits int of every TypeBinding
- final int IsArrayType = 0x0001;
- final int IsBaseType = 0x0002;
- final int IsNestedType = 0x0004;
- final int IsMemberType = 0x0008;
- final int MemberTypeMask = IsNestedType | IsMemberType;
- final int IsLocalType = 0x0010;
- final int LocalTypeMask = IsNestedType | IsLocalType;
- final int IsAnonymousType = 0x0020;
- final int AnonymousTypeMask = LocalTypeMask | IsAnonymousType;
- final int IsBinaryBinding = 0x0040;
-
- // for the type hierarchy check used by ClassScope
- final int BeginHierarchyCheck = 0x0100;
- final int EndHierarchyCheck = 0x0200;
-
+ long IsArrayType = ASTNode.Bit1;
+ long IsBaseType = ASTNode.Bit2;
+ long IsNestedType = ASTNode.Bit3;
+ long IsMemberType = ASTNode.Bit4;
+ long MemberTypeMask = IsNestedType | IsMemberType;
+ long IsLocalType = ASTNode.Bit5;
+ long LocalTypeMask = IsNestedType | IsLocalType;
+ long IsAnonymousType = ASTNode.Bit6;
+ long AnonymousTypeMask = LocalTypeMask | IsAnonymousType;
+ long IsBinaryBinding = ASTNode.Bit7;
+
+ // for the type cycle hierarchy check used by ClassScope
+ long BeginHierarchyCheck = ASTNode.Bit9; // type
+ long EndHierarchyCheck = ASTNode.Bit10; // type
+ long HasParameterAnnotations = ASTNode.Bit11; // method
+
// test bit to see if default abstract methods were computed
- final int KnowsDefaultAbstractMethods = 0x0400;
+ long KnowsDefaultAbstractMethods = ASTNode.Bit11;
// Reusable bit currently used by Scopes
- final int InterfaceVisited = 0x0800;
+ long InterfaceVisited = ASTNode.Bit12;
// test bits to see if parts of binary types are faulted
- final int AreFieldsComplete = 0x1000;
- final int AreMethodsComplete = 0x2000;
+ long AreFieldsComplete = ASTNode.Bit13;
+ long AreMethodsComplete = ASTNode.Bit14;
// test bit to avoid asking a type for a member type (includes inherited member types)
- final int HasNoMemberTypes = 0x4000;
+ long HasNoMemberTypes = ASTNode.Bit15;
// test bit to identify if the type's hierarchy is inconsistent
- final int HierarchyHasProblems = 0x8000;
+ long HierarchyHasProblems = ASTNode.Bit16;
+
+ // set for parameterized type NOT of the form X,?>
+ long IsBoundParameterizedType = ASTNode.Bit24;
+
+ // used by BinaryTypeBinding
+ long HasUnresolvedTypeVariables = ASTNode.Bit25;
+ long HasUnresolvedSuperclass = ASTNode.Bit26;
+ long HasUnresolvedSuperinterfaces = ASTNode.Bit27;
+ long HasUnresolvedEnclosingType = ASTNode.Bit28;
+ long HasUnresolvedMemberTypes = ASTNode.Bit29;
+
+ long HasTypeVariable = ASTNode.Bit30; // set either for type variables (direct) or parameterized types indirectly referencing type variables
+ long HasDirectWildcard = ASTNode.Bit31; // set for parameterized types directly referencing wildcards
+
+ // for the annotation cycle hierarchy check used by ClassScope
+ long BeginAnnotationCheck = ASTNode.Bit32L;
+ long EndAnnotationCheck = ASTNode.Bit33L;
+
+ // standard annotations
+ // 9-bits for targets
+ long AnnotationResolved = ASTNode.Bit34L;
+ long AnnotationTarget = ASTNode.Bit35L; // @Target({}) only sets this bit
+ long AnnotationForType = ASTNode.Bit36L;
+ long AnnotationForField = ASTNode.Bit37L;
+ long AnnotationForMethod = ASTNode.Bit38L;
+ long AnnotationForParameter = ASTNode.Bit39L;
+ long AnnotationForConstructor = ASTNode.Bit40L;
+ long AnnotationForLocalVariable = ASTNode.Bit41L;
+ long AnnotationForAnnotationType = ASTNode.Bit42L;
+ long AnnotationForPackage = ASTNode.Bit43L;
+ long AnnotationTargetMASK = AnnotationTarget
+ | AnnotationForType | AnnotationForField
+ | AnnotationForMethod | AnnotationForParameter
+ | AnnotationForConstructor | AnnotationForLocalVariable
+ | AnnotationForAnnotationType | AnnotationForPackage;
+ // 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention
+ long AnnotationSourceRetention = ASTNode.Bit44L;
+ long AnnotationClassRetention = ASTNode.Bit45L;
+ long AnnotationRuntimeRetention = AnnotationSourceRetention | AnnotationClassRetention;
+ long AnnotationRetentionMASK = AnnotationSourceRetention | AnnotationClassRetention | AnnotationRuntimeRetention;
+ // marker annotations
+ long AnnotationDeprecated = ASTNode.Bit46L;
+ long AnnotationDocumented = ASTNode.Bit47L;
+ long AnnotationInherited = ASTNode.Bit48L;
+ long AnnotationOverride = ASTNode.Bit49L;
+ long AnnotationSuppressWarnings = ASTNode.Bit50L;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index c6cd627..43455eb 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -10,7 +10,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
/*
* Not all fields defined by this type (& its subclasses) are initialized when it is created.
@@ -24,13 +26,42 @@ import org.eclipse.jdt.core.compiler.CharOperation;
*/
abstract public class TypeBinding extends Binding implements BaseTypes, TagBits, TypeConstants, TypeIds {
public int id = NoId;
- public int tagBits = 0; // See values in the interface TagBits below
+ public long tagBits = 0; // See values in the interface TagBits below
+/**
+ * Match a well-known type id to its binding
+ */
+public static final TypeBinding wellKnownType(Scope scope, int id) {
+ switch (id) {
+ case T_boolean :
+ return BooleanBinding;
+ case T_byte :
+ return ByteBinding;
+ case T_char :
+ return CharBinding;
+ case T_short :
+ return ShortBinding;
+ case T_double :
+ return DoubleBinding;
+ case T_float :
+ return FloatBinding;
+ case T_int :
+ return IntBinding;
+ case T_long :
+ return LongBinding;
+ case T_JavaLangObject :
+ return scope.getJavaLangObject();
+ case T_JavaLangString :
+ return scope.getJavaLangString();
+ default :
+ return null;
+ }
+ }
/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
-public final int bindingType() {
- return TYPE;
+public int kind() {
+ return Binding.TYPE;
}
/* Answer true if the receiver can be instantiated
*/
@@ -38,13 +69,26 @@ public boolean canBeInstantiated() {
return !isBaseType();
}
/**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+ // no substitute by default
+}
+/*
+ * genericTypeSignature
+ */
+public char[] computeUniqueKey() {
+ return genericTypeSignature();
+}
+/**
* Answer the receiver's constant pool name.
* NOTE: This method should only be used during/after code gen.
* e.g. 'java/lang/Object'
*/
public abstract char[] constantPoolName();
-String debugName() {
+public String debugName() {
return new String(readableName());
}
/*
@@ -53,35 +97,101 @@ String debugName() {
public int dimensions(){
return 0;
}
+/* Answer the receiver's enclosing type... null if the receiver is a top level type.
+*/
+
+public ReferenceBinding enclosingType() {
+ return null;
+}
+public TypeBinding erasure() {
+ return this;
+}
+/**
+ * Returns the type to use for generic cast, or null if none required
+ */
+public TypeBinding genericCast(TypeBinding otherType) {
+ if (this == otherType) return null;
+ if (otherType.isWildcard() && ((WildcardBinding)otherType).kind != Wildcard.EXTENDS) return null;
+ TypeBinding otherErasure = otherType.erasure();
+ if (otherErasure == this.erasure()) return null;
+ return otherErasure;
+}
+
+/**
+ * Answer the receiver classfile signature.
+ * Arrays & base types do not distinguish between signature() & constantPoolName().
+ * NOTE: This method should only be used during/after code gen.
+ */
+public char[] genericTypeSignature() {
+ return signature();
+}
public abstract PackageBinding getPackage();
+public boolean isAnnotationType() {
+ return false;
+}
/* Answer true if the receiver is an array
*/
-
public final boolean isArrayType() {
return (tagBits & IsArrayType) != 0;
}
/* Answer true if the receiver is a base type
*/
-
public final boolean isBaseType() {
return (tagBits & IsBaseType) != 0;
}
+
+
+/**
+ * Returns true if parameterized type AND not of the form List>
+ */
+public boolean isBoundParameterizedType() {
+ return (this.tagBits & TagBits.IsBoundParameterizedType) != 0;
+}
public boolean isClass() {
return false;
}
/* Answer true if the receiver type can be assigned to the argument type (right)
*/
-
public abstract boolean isCompatibleWith(TypeBinding right);
+
+public boolean isEnum() {
+ return false;
+}
+/**
+ * Returns true if a type is identical to another one,
+ * or for generic types, true if compared to its raw type.
+ */
+public boolean isEquivalentTo(TypeBinding otherType) {
+ if (this == otherType) return true;
+ if (otherType == null) return false;
+ if (otherType.isWildcard()) // wildcard
+ return ((WildcardBinding) otherType).boundCheck(this);
+ return false;
+}
+
+public boolean isGenericType() {
+ return false;
+}
+
/* Answer true if the receiver's hierarchy has problems (always false for arrays & base types)
*/
-
public final boolean isHierarchyInconsistent() {
return (tagBits & HierarchyHasProblems) != 0;
}
public boolean isInterface() {
return false;
}
+public final boolean isLocalType() {
+ return (tagBits & IsLocalType) != 0;
+}
+
+public final boolean isMemberType() {
+ return (tagBits & IsMemberType) != 0;
+}
+
+public final boolean isNestedType() {
+ return (tagBits & IsNestedType) != 0;
+}
public final boolean isNumericType() {
switch (id) {
case T_int :
@@ -97,6 +207,170 @@ public final boolean isNumericType() {
}
}
+/**
+ * Returns true if the type is parameterized, e.g. List
+ */
+public boolean isParameterizedType() {
+ return false;
+}
+
+public boolean isPartOfRawType() {
+ TypeBinding current = this;
+ do {
+ if (current.isRawType())
+ return true;
+ } while ((current = current.enclosingType()) != null);
+ return false;
+}
+
+/**
+ * Returns true if the two types are statically known to be different at compile-time,
+ * e.g. a type variable is not probably known to be distinct from another type
+ */
+public boolean isProvablyDistinctFrom(TypeBinding otherType, int depth) {
+ if (this == otherType) return false;
+ if (depth > 1) return true;
+ switch (otherType.kind()) {
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ return false;
+ }
+ switch(kind()) {
+
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ return false;
+
+ case Binding.PARAMETERIZED_TYPE :
+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this;
+ if (parameterizedType.type.isProvablyDistinctFrom(otherType.erasure(), depth)) return true;
+ switch (otherType.kind()) {
+ case Binding.GENERIC_TYPE :
+ case Binding.RAW_TYPE :
+ return false;
+ case Binding.PARAMETERIZED_TYPE :
+ TypeBinding[] arguments = parameterizedType.arguments;
+ if (arguments == null) return false;
+ ParameterizedTypeBinding otherParameterizedType = (ParameterizedTypeBinding) otherType;
+ TypeBinding[] otherArguments = otherParameterizedType.arguments;
+ if (otherArguments == null) return false;
+ for (int i = 0, length = arguments.length; i < length; i++) {
+ if (arguments[i].isProvablyDistinctFrom(otherArguments[i], depth+1)) return true;
+ }
+ return false;
+
+ }
+ break;
+
+ case Binding.RAW_TYPE :
+ return this.erasure().isProvablyDistinctFrom(otherType.erasure(), 0);
+
+ case Binding.GENERIC_TYPE :
+ return this != otherType.erasure();
+ }
+ return this != otherType;
+}
+
+public boolean isRawType() {
+ return false;
+}
+
+/**
+ * JLS(3) 4.7
+ */
+public boolean isReifiable() {
+
+ TypeBinding leafType = leafComponentType();
+ if (!(leafType instanceof ReferenceBinding))
+ return true;
+ ReferenceBinding current = (ReferenceBinding) leafType;
+ do {
+ switch(current.kind()) {
+
+ case Binding.TYPE_PARAMETER :
+ case Binding.WILDCARD_TYPE :
+ case Binding.GENERIC_TYPE :
+ return false;
+
+ case Binding.PARAMETERIZED_TYPE :
+ if (isBoundParameterizedType())
+ return false;
+ break;
+
+ case Binding.RAW_TYPE :
+ return true;
+ }
+ if (current.isStatic())
+ return true;
+ } while ((current = current.enclosingType()) != null);
+ return true;
+}
+
+// JLS3: 4.5.1.1
+public boolean isTypeArgumentContainedBy(TypeBinding otherArgument) {
+ if (this == otherArgument)
+ return true;
+ TypeBinding lowerBound = this;
+ TypeBinding upperBound = this;
+ if (isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) this;
+ switch(wildcard.kind) {
+ case Wildcard.EXTENDS :
+ upperBound = wildcard.bound;
+ lowerBound = null;
+ break;
+ case Wildcard. SUPER :
+ upperBound = wildcard.typeVariable();
+ lowerBound = wildcard.bound;
+ break;
+ case Wildcard.UNBOUND :
+ upperBound = wildcard.typeVariable();
+ lowerBound = null;
+ }
+ }
+ if (otherArgument.isWildcard()) {
+ WildcardBinding otherWildcard = (WildcardBinding) otherArgument;
+ switch(otherWildcard.kind) {
+ case Wildcard.EXTENDS:
+ return upperBound != null && upperBound.isCompatibleWith(otherWildcard.bound);
+
+ case Wildcard.SUPER :
+ return lowerBound != null && otherWildcard.bound.isCompatibleWith(lowerBound);
+
+ case Wildcard.UNBOUND :
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns true if the type was declared as a type variable
+ */
+public boolean isTypeVariable() {
+ return false;
+}
+/**
+ * Returns true if wildcard type of the form '?' (no bound)
+ */
+public boolean isUnboundWildcard() {
+ return false;
+}
+
+/**
+ * Returns true if the type is a wildcard
+ */
+public boolean isWildcard() {
+ return false;
+}
+
+/**
+ * Meant to be invoked on compatible types, to figure if unchecked conversion is necessary
+ */
+public boolean needsUncheckedConversion(TypeBinding targetType) {
+ return false;
+}
+
public TypeBinding leafComponentType(){
return this;
}
@@ -121,45 +395,22 @@ public char[] qualifiedPackageName() {
*/
public abstract char[] qualifiedSourceName();
-/* Answer the receiver's signature.
-*
-* Arrays & base types do not distinguish between signature() & constantPoolName().
-*
-* NOTE: This method should only be used during/after code gen.
-*/
+/**
+ * Answer the receiver classfile signature.
+ * Arrays & base types do not distinguish between signature() & constantPoolName().
+ * NOTE: This method should only be used during/after code gen.
+ */
public char[] signature() {
return constantPoolName();
}
+
public abstract char[] sourceName();
-/**
- * Match a well-known type id to its binding
- */
-public static final TypeBinding wellKnownType(Scope scope, int id) {
- switch (id) {
- case T_boolean :
- return BooleanBinding;
- case T_byte :
- return ByteBinding;
- case T_char :
- return CharBinding;
- case T_short :
- return ShortBinding;
- case T_double :
- return DoubleBinding;
- case T_float :
- return FloatBinding;
- case T_int :
- return IntBinding;
- case T_long :
- return LongBinding;
- case T_Object :
- return scope.getJavaLangObject();
- case T_String :
- return scope.getJavaLangString();
- default :
- return null;
- }
- }
+public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment environment) {
+ // subclasses must override if they wrap another type binding
+}
+public TypeVariableBinding[] typeVariables() {
+ return NoTypeVariables;
+}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/src/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 5f6064f..3a31669 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -11,67 +11,130 @@
package org.eclipse.jdt.internal.compiler.lookup;
public interface TypeConstants {
- final char[] JAVA = "java".toCharArray(); //$NON-NLS-1$
- final char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
- final char[] IO = "io".toCharArray(); //$NON-NLS-1$
- final char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
- final char[] CharArray_JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
- final char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
- final char[] CLONE = "clone".toCharArray(); //$NON-NLS-1$
- final char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
- final char[] MAIN = "main".toCharArray(); //$NON-NLS-1$
- final char[] SERIALVERSIONUID = "serialVersionUID".toCharArray(); //$NON-NLS-1$
- final char[] SERIALPERSISTENTFIELDS = "serialPersistentFields".toCharArray(); //$NON-NLS-1$
- final char[] READRESOLVE = "readResolve".toCharArray(); //$NON-NLS-1$
- final char[] WRITEREPLACE = "writeReplace".toCharArray(); //$NON-NLS-1$
- final char[] READOBJECT = "readObject".toCharArray(); //$NON-NLS-1$
- final char[] WRITEOBJECT = "writeObject".toCharArray(); //$NON-NLS-1$
- final char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
- final char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
- final char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
-
-
+ char[] JAVA = "java".toCharArray(); //$NON-NLS-1$
+ char[] LANG = "lang".toCharArray(); //$NON-NLS-1$
+ char[] IO = "io".toCharArray(); //$NON-NLS-1$
+ char[] ANNOTATION = "annotation".toCharArray(); //$NON-NLS-1$
+ char[] REFLECT = "reflect".toCharArray(); //$NON-NLS-1$
+ char[] LENGTH = "length".toCharArray(); //$NON-NLS-1$
+ char[] CLONE = "clone".toCharArray(); //$NON-NLS-1$
+ char[] GETCLASS = "getClass".toCharArray(); //$NON-NLS-1$
+ char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
+ char[] MAIN = "main".toCharArray(); //$NON-NLS-1$
+ char[] SERIALVERSIONUID = "serialVersionUID".toCharArray(); //$NON-NLS-1$
+ char[] SERIALPERSISTENTFIELDS = "serialPersistentFields".toCharArray(); //$NON-NLS-1$
+ char[] READRESOLVE = "readResolve".toCharArray(); //$NON-NLS-1$
+ char[] WRITEREPLACE = "writeReplace".toCharArray(); //$NON-NLS-1$
+ char[] READOBJECT = "readObject".toCharArray(); //$NON-NLS-1$
+ char[] WRITEOBJECT = "writeObject".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ENUM = "java.lang.Enum".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_ANNOTATION = "java.lang.annotation.Annotation".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
+ char[] ANONYM_PREFIX = "new ".toCharArray(); //$NON-NLS-1$
+ char[] ANONYM_SUFFIX = "(){}".toCharArray(); //$NON-NLS-1$
+ char[] WILDCARD_NAME = { '?' };
+ char[] WILDCARD_SUPER = " super ".toCharArray(); //$NON-NLS-1$
+ char[] WILDCARD_EXTENDS = " extends ".toCharArray(); //$NON-NLS-1$
+ char[] WILDCARD_MINUS = { '-' };
+ char[] WILDCARD_STAR = { '*' };
+ char[] WILDCARD_PLUS = { '+' };
+ char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
+ char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
+ char[] INT = "int".toCharArray(); //$NON-NLS-1$
+ char[] LONG = "long".toCharArray(); //$NON-NLS-1$
+ char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
+ char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
+ char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
+ char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
+ char[] NULL = "null".toCharArray(); //$NON-NLS-1$
+ char[] VOID = "void".toCharArray(); //$NON-NLS-1$
+ char[] VALUE = "value".toCharArray(); //$NON-NLS-1$
+ char[] VALUES = "values".toCharArray(); //$NON-NLS-1$
+ char[] VALUEOF = "valueOf".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_SOURCE = "SOURCE".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_CLASS = "CLASS".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_RUNTIME = "RUNTIME".toCharArray(); //$NON-NLS-1$
+ char[] ANNOTATION_PREFIX = "@".toCharArray(); //$NON-NLS-1$
+ char[] ANNOTATION_SUFFIX = "()".toCharArray(); //$NON-NLS-1$
+ char[] TYPE = "TYPE".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_FIELD = "FIELD".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_METHOD = "METHOD".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_PARAMETER = "PARAMETER".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_CONSTRUCTOR = "CONSTRUCTOR".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_LOCAL_VARIABLE = "LOCAL_VARIABLE".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_ANNOTATION_TYPE = "ANNOTATION_TYPE".toCharArray(); //$NON-NLS-1$
+ char[] UPPER_PACKAGE = "PACKAGE".toCharArray(); //$NON-NLS-1$
+
// Constant compound names
- final char[][] JAVA_LANG = {JAVA, LANG};
- final char[][] JAVA_IO = {JAVA, IO};
- final char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_CLASSNOTFOUNDEXCEPTION = {JAVA, LANG, "ClassNotFoundException".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_CLONEABLE = {JAVA, LANG, "Cloneable".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_EXCEPTION = {JAVA, LANG, "Exception".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_ERROR = {JAVA, LANG, "Error".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_NOCLASSDEFERROR = {JAVA, LANG, "NoClassDefError".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_OBJECT = {JAVA, LANG, OBJECT};
- final char[][] JAVA_LANG_STRING = {JAVA, LANG, "String".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_STRINGBUFFER = {JAVA, LANG, "StringBuffer".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_SYSTEM = {JAVA, LANG, "System".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_RUNTIMEEXCEPTION = {JAVA, LANG, "RuntimeException".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_THROWABLE = {JAVA, LANG, "Throwable".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_REFLECT_CONSTRUCTOR = {JAVA, LANG, REFLECT, "Constructor".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_IO_PRINTSTREAM = {JAVA, IO, "PrintStream".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_IO_SERIALIZABLE = {JAVA, IO, "Serializable".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_BYTE = {JAVA, LANG, "Byte".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_SHORT = {JAVA, LANG, "Short".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_CHARACTER = {JAVA, LANG, "Character".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_INTEGER = {JAVA, LANG, "Integer".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_LONG = {JAVA, LANG, "Long".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_FLOAT = {JAVA, LANG, "Float".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_DOUBLE = {JAVA, LANG, "Double".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_BOOLEAN = {JAVA, LANG, "Boolean".toCharArray()}; //$NON-NLS-1$
- final char[][] JAVA_LANG_VOID = {JAVA, LANG, "Void".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG = {JAVA, LANG};
+ char[][] JAVA_IO = {JAVA, IO};
+ char[][] JAVA_LANG_ANNOTATION_ANNOTATION = {JAVA, LANG, ANNOTATION, "Annotation".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ASSERTIONERROR = {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_CLASS = {JAVA, LANG, "Class".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_CLASSNOTFOUNDEXCEPTION = {JAVA, LANG, "ClassNotFoundException".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_CLONEABLE = {JAVA, LANG, "Cloneable".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ENUM = {JAVA, LANG, "Enum".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_EXCEPTION = {JAVA, LANG, "Exception".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ERROR = {JAVA, LANG, "Error".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ILLEGALARGUMENTEXCEPTION = {JAVA, LANG, "IllegalArgumentException".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ITERABLE = {JAVA, LANG, "Iterable".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_NOCLASSDEFERROR = {JAVA, LANG, "NoClassDefError".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_OBJECT = {JAVA, LANG, OBJECT};
+ char[][] JAVA_LANG_STRING = {JAVA, LANG, "String".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_STRINGBUFFER = {JAVA, LANG, "StringBuffer".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_STRINGBUILDER = {JAVA, LANG, "StringBuilder".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_SYSTEM = {JAVA, LANG, "System".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_RUNTIMEEXCEPTION = {JAVA, LANG, "RuntimeException".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_THROWABLE = {JAVA, LANG, "Throwable".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_REFLECT_CONSTRUCTOR = {JAVA, LANG, REFLECT, "Constructor".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_IO_PRINTSTREAM = {JAVA, IO, "PrintStream".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_IO_SERIALIZABLE = {JAVA, IO, "Serializable".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_BYTE = {JAVA, LANG, "Byte".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_SHORT = {JAVA, LANG, "Short".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_CHARACTER = {JAVA, LANG, "Character".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_INTEGER = {JAVA, LANG, "Integer".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_LONG = {JAVA, LANG, "Long".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_FLOAT = {JAVA, LANG, "Float".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_DOUBLE = {JAVA, LANG, "Double".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_BOOLEAN = {JAVA, LANG, "Boolean".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_VOID = {JAVA, LANG, "Void".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_UTIL_ITERATOR = {JAVA, "util".toCharArray(), "Iterator".toCharArray()}; //$NON-NLS-1$//$NON-NLS-2$
+ char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_OVERRIDE = {JAVA, LANG, "Override".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_RETENTION = {JAVA, LANG, ANNOTATION, "Retention".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_SUPPRESSWARNINGS = {JAVA, LANG, "SuppressWarnings".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_TARGET = {JAVA, LANG, ANNOTATION, "Target".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_RETENTIONPOLICY = {JAVA, LANG, ANNOTATION, "RetentionPolicy".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_ELEMENTTYPE = {JAVA, LANG, ANNOTATION, "ElementType".toCharArray()}; //$NON-NLS-1$
+
// Constants used by the flow analysis
- final int EqualOrMoreSpecific = -1;
- final int NotRelated = 0;
- final int MoreGeneric = 1;
+ int EqualOrMoreSpecific = -1;
+ int NotRelated = 0;
+ int MoreGeneric = 1;
- // Method collections
- final TypeBinding[] NoParameters = new TypeBinding[0];
- final ReferenceBinding[] NoExceptions = new ReferenceBinding[0];
- final ReferenceBinding[] AnyException = new ReferenceBinding[] { null }; // special handler for all exceptions
- // Type collections
- final FieldBinding[] NoFields = new FieldBinding[0];
- final MethodBinding[] NoMethods = new MethodBinding[0];
- final ReferenceBinding[] NoSuperInterfaces = new ReferenceBinding[0];
- final ReferenceBinding[] NoMemberTypes = new ReferenceBinding[0];
+ // Shared binding collections
+ TypeBinding[] NoParameters = new TypeBinding[0];
+ ReferenceBinding[] NoExceptions = new ReferenceBinding[0];
+ ReferenceBinding[] AnyException = new ReferenceBinding[] { null }; // special handler for all exceptions
+ FieldBinding[] NoFields = new FieldBinding[0];
+ MethodBinding[] NoMethods = new MethodBinding[0];
+ ReferenceBinding[] NoSuperInterfaces = new ReferenceBinding[0];
+ ReferenceBinding[] NoMemberTypes = new ReferenceBinding[0];
+ TypeVariableBinding[] NoTypeVariables = new TypeVariableBinding[0];
+
+ // Synthetics
+ char[] INIT = "".toCharArray(); //$NON-NLS-1$
+ char[] CLINIT = "".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_ENUM_VALUES = "ENUM$VALUES".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_ASSERT_DISABLED = "$assertionsDisabled".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_CLASS = "class$".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_OUTER_LOCAL_PREFIX = "val$".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_ENCLOSING_INSTANCE_PREFIX = "this$".toCharArray(); //$NON-NLS-1$
+ char[] SYNTHETIC_ACCESS_METHOD_PREFIX = "access$".toCharArray(); //$NON-NLS-1$
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/src/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
index 5fe8af0..0e8beeb 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
@@ -11,11 +11,12 @@
package org.eclipse.jdt.internal.compiler.lookup;
public interface TypeIds {
- //base type void null undefined Object String
- //should have an id that is 0<= id <= 15
+ //base type void null undefined Object String
+ //should have an id that is 0<= id <= 15
+ // The IDs below must be representable using 4 bits so as to fit in operator signatures.
final int T_undefined = 0; // should not be changed
- final int T_Object = 1;
+ final int T_JavaLangObject = 1;
final int T_char = 2;
final int T_byte = 3;
final int T_short = 4;
@@ -25,16 +26,11 @@ public interface TypeIds {
final int T_double = 8;
final int T_float = 9;
final int T_int = 10;
- final int T_String = 11;
+ final int T_JavaLangString = 11;
final int T_null = 12;
- //final int T_extendedDouble = 13;
- //final int T_extendedLong = 14
//=========end of 4 bits constraint===========
- final int T_JavaLangObject = T_Object; // for consistency
- final int T_JavaLangString = T_String; // for consistency
-
// well-known exception types
final int T_JavaLangClass = 16;
final int T_JavaLangStringBuffer = 17;
@@ -58,18 +54,38 @@ public interface TypeIds {
final int T_JavaLangBoolean = 33;
final int T_JavaLangVoid = 34;
- // 1.4 feature
+ // 1.4 features
final int T_JavaLangAssertionError = 35;
-
+
// array interfaces
final int T_JavaLangCloneable = 36;
final int T_JavaIoSerializable = 37;
+
+ // 1.5 features
+ final int T_JavaLangIterable = 38;
+ final int T_JavaUtilIterator = 39;
+ final int T_JavaLangStringBuilder = 40;
+ final int T_JavaLangEnum = 41;
+ final int T_JavaLangIllegalArgumentException = 42;
+ final int T_JavaLangAnnotationAnnotation = 43;
+ final int T_JavaLangDeprecated = 44;
+ final int T_JavaLangAnnotationDocumented = 45;
+ final int T_JavaLangAnnotationInherited = 46;
+ final int T_JavaLangOverride = 47;
+ final int T_JavaLangAnnotationRetention = 48;
+ final int T_JavaLangSuppressWarnings = 49;
+ final int T_JavaLangAnnotationTarget = 50;
+ final int T_JavaLangAnnotationRetentionPolicy = 51;
+ final int T_JavaLangAnnotationElementType = 52;
final int NoId = Integer.MAX_VALUE;
+ public static final int IMPLICIT_CONVERSION_MASK = 0xFF;
+ public static final int COMPILE_TYPE_MASK = 0xF;
+
// implicit conversions: to (note: booleans are integers at runtime)
final int Boolean2Int = T_boolean + (T_int << 4);
- final int Boolean2String = T_boolean + (T_String << 4);
+ final int Boolean2String = T_boolean + (T_JavaLangString << 4);
final int Boolean2Boolean = T_boolean + (T_boolean << 4);
final int Byte2Byte = T_byte + (T_byte << 4);
final int Byte2Short = T_byte + (T_short << 4);
@@ -78,7 +94,7 @@ public interface TypeIds {
final int Byte2Long = T_byte + (T_long << 4);
final int Byte2Float = T_byte + (T_float << 4);
final int Byte2Double = T_byte + (T_double << 4);
- final int Byte2String = T_byte + (T_String << 4);
+ final int Byte2String = T_byte + (T_JavaLangString << 4);
final int Short2Byte = T_short + (T_byte << 4);
final int Short2Short = T_short + (T_short << 4);
final int Short2Char = T_short + (T_char << 4);
@@ -86,7 +102,7 @@ public interface TypeIds {
final int Short2Long = T_short + (T_long << 4);
final int Short2Float = T_short + (T_float << 4);
final int Short2Double = T_short + (T_double << 4);
- final int Short2String = T_short + (T_String << 4);
+ final int Short2String = T_short + (T_JavaLangString << 4);
final int Char2Byte = T_char + (T_byte << 4);
final int Char2Short = T_char + (T_short << 4);
final int Char2Char = T_char + (T_char << 4);
@@ -94,7 +110,7 @@ public interface TypeIds {
final int Char2Long = T_char + (T_long << 4);
final int Char2Float = T_char + (T_float << 4);
final int Char2Double = T_char + (T_double << 4);
- final int Char2String = T_char + (T_String << 4);
+ final int Char2String = T_char + (T_JavaLangString << 4);
final int Int2Byte = T_int + (T_byte << 4);
final int Int2Short = T_int + (T_short << 4);
final int Int2Char = T_int + (T_char << 4);
@@ -102,7 +118,7 @@ public interface TypeIds {
final int Int2Long = T_int + (T_long << 4);
final int Int2Float = T_int + (T_float << 4);
final int Int2Double = T_int + (T_double << 4);
- final int Int2String = T_int + (T_String << 4);
+ final int Int2String = T_int + (T_JavaLangString << 4);
final int Long2Byte = T_long + (T_byte << 4);
final int Long2Short = T_long + (T_short << 4);
final int Long2Char = T_long + (T_char << 4);
@@ -110,7 +126,7 @@ public interface TypeIds {
final int Long2Long = T_long + (T_long << 4);
final int Long2Float = T_long + (T_float << 4);
final int Long2Double = T_long + (T_double << 4);
- final int Long2String = T_long + (T_String << 4);
+ final int Long2String = T_long + (T_JavaLangString << 4);
final int Float2Byte = T_float + (T_byte << 4);
final int Float2Short = T_float + (T_short << 4);
final int Float2Char = T_float + (T_char << 4);
@@ -118,7 +134,7 @@ public interface TypeIds {
final int Float2Long = T_float + (T_long << 4);
final int Float2Float = T_float + (T_float << 4);
final int Float2Double = T_float + (T_double << 4);
- final int Float2String = T_float + (T_String << 4);
+ final int Float2String = T_float + (T_JavaLangString << 4);
final int Double2Byte = T_double + (T_byte << 4);
final int Double2Short = T_double + (T_short << 4);
final int Double2Char = T_double + (T_char << 4);
@@ -126,9 +142,11 @@ public interface TypeIds {
final int Double2Long = T_double + (T_long << 4);
final int Double2Float = T_double + (T_float << 4);
final int Double2Double = T_double + (T_double << 4);
- final int Double2String = T_double + (T_String << 4);
- final int String2String = T_String + (T_String << 4);
- final int Object2String = T_Object + (T_String << 4);
- final int Null2String = T_null + (T_String << 4);
- final int Object2Object = T_Object + (T_Object << 4);
+ final int Double2String = T_double + (T_JavaLangString << 4);
+ final int String2String = T_JavaLangString + (T_JavaLangString << 4);
+ final int Object2String = T_JavaLangObject + (T_JavaLangString << 4);
+ final int Null2String = T_null + (T_JavaLangString << 4);
+ final int Object2Object = T_JavaLangObject + (T_JavaLangObject << 4);
+ final int BOXING = 0x200;
+ final int UNBOXING = 0x400;
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
new file mode 100644
index 0000000..eb4e4b1
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/**
+ * Binding for a type parameter, held by source/binary type or method.
+ */
+public class TypeVariableBinding extends ReferenceBinding {
+
+ public Binding declaringElement; // binding of declaring type or method
+ public int rank; // declaration rank, can be used to match variable in parameterized type
+
+ /**
+ * Denote the first explicit (binding) bound amongst the supertypes (from declaration in source)
+ * If no superclass was specified, then it denotes the first superinterface, or null if none was specified.
+ */
+ public ReferenceBinding firstBound;
+
+ // actual resolved variable supertypes (if no superclass bound, then associated to Object)
+ public ReferenceBinding superclass;
+ public ReferenceBinding[] superInterfaces;
+ public char[] genericTypeSignature;
+
+ public TypeVariableBinding(char[] sourceName, Binding declaringElement, int rank) {
+ this.sourceName = sourceName;
+ this.declaringElement = declaringElement;
+ this.rank = rank;
+ this.modifiers = AccPublic | AccGenericSignature; // treat type var as public
+ this.tagBits |= HasTypeVariable;
+ }
+
+ public int kind() {
+ return TYPE_PARAMETER;
+ }
+
+ /**
+ * Returns true if the argument type satisfies all bounds of the type parameter
+ */
+ public boolean boundCheck(Substitution substitution, TypeBinding argumentType) {
+ if (argumentType == NullBinding || this == argumentType)
+ return true;
+ if (!(argumentType instanceof ReferenceBinding || argumentType.isArrayType()))
+ return false;
+
+ if (argumentType.isWildcard()) {
+ WildcardBinding wildcard = (WildcardBinding) argumentType;
+ switch (wildcard.kind) {
+ case Wildcard.SUPER :
+ if (!boundCheck(substitution, wildcard.bound)) return false;
+ break;
+ case Wildcard.UNBOUND :
+ if (this == wildcard.typeVariable())
+ return true;
+ break;
+ }
+ }
+// if (this == argumentType)
+// return true;
+ boolean hasSubstitution = substitution != null;
+ if (this.superclass.id != T_JavaLangObject && !argumentType.isCompatibleWith(hasSubstitution ? substitution.substitute(this.superclass) : this.superclass)) {
+ return false;
+ }
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (!argumentType.isCompatibleWith(hasSubstitution ? substitution.substitute(this.superInterfaces[i]) : this.superInterfaces[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+ */
+ public boolean canBeInstantiated() {
+ return false;
+ }
+ /**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+ public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+ // cannot infer anything from a null type
+ if (otherType == NullBinding) return;
+
+ TypeBinding[] variableSubstitutes = (TypeBinding[])substitutes.get(this);
+ if (variableSubstitutes != null) {
+ int length = variableSubstitutes.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding substitute = variableSubstitutes[i];
+ if (substitute == otherType) return; // already there
+ if (substitute == null) {
+ variableSubstitutes[i] = otherType;
+ return;
+ }
+ }
+ // no free spot found, need to grow
+ System.arraycopy(variableSubstitutes, 0, variableSubstitutes = new TypeBinding[2*length], 0, length);
+ variableSubstitutes[length] = otherType;
+ substitutes.put(this, variableSubstitutes);
+ }
+ }
+
+ public char[] constantPoolName() { /* java/lang/Object */
+ if (this.firstBound != null) {
+ return this.firstBound.constantPoolName();
+ }
+ return this.superclass.constantPoolName(); // java/lang/Object
+ }
+ /*
+ * declaringUniqueKey : genericTypeSignature
+ * p.X { ... } --> Lp/X;:TT;
+ */
+ public char[] computeUniqueKey() {
+ char[] declaringKey = this.declaringElement.computeUniqueKey();
+ int declaringLength = declaringKey.length;
+ char[] sig = genericTypeSignature();
+ int sigLength = sig.length;
+ char[] uniqueKey = new char[declaringLength + 1 + sigLength];
+ System.arraycopy(declaringKey, 0, uniqueKey, 0, declaringLength);
+ uniqueKey[declaringLength] = ':';
+ System.arraycopy(sig, 0, uniqueKey, declaringLength+1, sigLength);
+ return uniqueKey;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+ */
+ public String debugName() {
+ return new String(this.sourceName);
+ }
+ public TypeBinding erasure() {
+ if (this.firstBound != null) {
+ return this.firstBound.erasure();
+ }
+ return this.superclass; // java/lang/Object
+ }
+
+/**
+ * Find supertype which erases to a given well-known type, or null if not found
+ * (using id avoids triggering the load of well-known type: 73740)
+ * NOTE: only works for erasures of well-known types, as random other types may share
+ * same id though being distincts.
+ * Override super-method since erasure() is answering firstBound (first supertype) already
+ */
+public ReferenceBinding findSuperTypeErasingTo(int erasureId, boolean erasureIsClass) {
+
+// if (this.id == erasureId) return this; // no ID for type variable
+ ReferenceBinding currentType = this;
+ // iterate superclass to avoid recording interfaces if searched supertype is class
+ if (erasureIsClass) {
+ while ((currentType = currentType.superclass()) != null) {
+ if (currentType.erasure().id == erasureId) return currentType;
+ }
+ return null;
+ }
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ } while ((currentType = currentType.superclass()) != null);
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ if ((currentType = interfaces[j]).erasure().id == erasureId)
+ return currentType;
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ return null;
+}
+/**
+ * Find supertype which erases to a given type, or null if not found
+ * Override super-method since erasure() is answering firstBound (first supertype) already
+ */
+public ReferenceBinding findSuperTypeErasingTo(ReferenceBinding erasure) {
+
+ if (this == erasure) return this;
+ ReferenceBinding currentType = this;
+ if (erasure.isClass()) {
+ while ((currentType = currentType.superclass()) != null) {
+ if (currentType.erasure() == erasure) return currentType;
+ }
+ return null;
+ }
+ ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+ int lastPosition = -1;
+ do {
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ } while ((currentType = currentType.superclass()) != null);
+
+ for (int i = 0; i <= lastPosition; i++) {
+ ReferenceBinding[] interfaces = interfacesToVisit[i];
+ for (int j = 0, length = interfaces.length; j < length; j++) {
+ if ((currentType = interfaces[j]).erasure() == erasure)
+ return currentType;
+
+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+ if (itsInterfaces != NoSuperInterfaces) {
+ if (++lastPosition == interfacesToVisit.length)
+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+ interfacesToVisit[lastPosition] = itsInterfaces;
+ }
+ }
+ }
+ return null;
+}
+
+ /**
+ * T::Ljava/util/Map;:Ljava/io/Serializable;
+ * T:LY
+ */
+ public char[] genericSignature() {
+ StringBuffer sig = new StringBuffer(10);
+ sig.append(this.sourceName).append(':');
+ int interfaceLength = this.superInterfaces.length;
+ if (interfaceLength == 0 || this.firstBound == this.superclass) {
+ sig.append(this.superclass.genericTypeSignature());
+ }
+ for (int i = 0; i < interfaceLength; i++) {
+ sig.append(':').append(this.superInterfaces[i].genericTypeSignature());
+ }
+ int sigLength = sig.length();
+ char[] genericSignature = new char[sigLength];
+ sig.getChars(0, sigLength, genericSignature, 0);
+ return genericSignature;
+ }
+ /**
+ * T::Ljava/util/Map;:Ljava/io/Serializable;
+ * T:LY
+ */
+ public char[] genericTypeSignature() {
+ if (this.genericTypeSignature != null) return this.genericTypeSignature;
+ return this.genericTypeSignature = CharOperation.concat('T', this.sourceName, ';');
+ }
+
+ /**
+ * Returns true if the type variable is directly bound to a given type
+ */
+ public boolean isErasureBoundTo(TypeBinding type) {
+ if (this.superclass.erasure() == type)
+ return true;
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (this.superInterfaces[i].erasure() == type)
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Returns true if the type was declared as a type variable
+ */
+ public boolean isTypeVariable() {
+ return true;
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#readableName()
+ */
+ public char[] readableName() {
+ return this.sourceName;
+ }
+
+ ReferenceBinding resolve(LookupEnvironment environment) {
+ if ((this.modifiers & AccUnresolved) == 0)
+ return this;
+
+ if (this.superclass != null)
+ this.superclass = BinaryTypeBinding.resolveUnresolvedType(this.superclass, environment, true);
+ if (this.firstBound != null)
+ this.firstBound = BinaryTypeBinding.resolveUnresolvedType(this.firstBound, environment, true);
+ ReferenceBinding[] interfaces = this.superInterfaces;
+ for (int i = interfaces.length; --i >= 0;)
+ interfaces[i] = BinaryTypeBinding.resolveUnresolvedType(interfaces[i], environment, true);
+ this.modifiers &= ~AccUnresolved;
+
+ // finish resolving the types
+ if (this.superclass != null)
+ this.superclass = BinaryTypeBinding.resolveType(this.superclass, environment, true);
+ if (this.firstBound != null)
+ this.firstBound = BinaryTypeBinding.resolveType(this.firstBound, environment, true);
+ for (int i = interfaces.length; --i >= 0;)
+ interfaces[i] = BinaryTypeBinding.resolveType(interfaces[i], environment, true);
+ return this;
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName()
+ */
+ public char[] shortReadableName() {
+ return this.readableName();
+ }
+ public ReferenceBinding superclass() {
+ return superclass;
+ }
+ public ReferenceBinding[] superInterfaces() {
+ return superInterfaces;
+ }
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(10);
+ buffer.append('<').append(this.sourceName);//.append('[').append(this.rank).append(']');
+ if (this.superclass != null && this.firstBound == this.superclass) {
+ buffer.append(" extends ").append(this.superclass.debugName()); //$NON-NLS-1$
+ }
+ if (this.superInterfaces != null && this.superInterfaces != NoSuperInterfaces) {
+ if (this.firstBound != this.superclass) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ }
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (i > 0 || this.firstBound == this.superclass) {
+ buffer.append(" & "); //$NON-NLS-1$
+ }
+ buffer.append(this.superInterfaces[i].debugName());
+ }
+ }
+ buffer.append('>');
+ return buffer.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index 65ff088..3b4e74b 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -13,29 +13,67 @@ package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
public class UnresolvedReferenceBinding extends ReferenceBinding {
- ReferenceBinding resolvedType;
+
+ReferenceBinding resolvedType;
+TypeBinding[] wrappers;
+
UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
this.compoundName = compoundName;
this.sourceName = compoundName[compoundName.length - 1]; // reasonable guess
this.fPackage = packageBinding;
+ this.wrappers = null;
+}
+void addWrapper(TypeBinding wrapper) {
+ if (this.wrappers == null) {
+ this.wrappers = new TypeBinding[] {wrapper};
+ } else {
+ int length = this.wrappers.length;
+ System.arraycopy(this.wrappers, 0, this.wrappers = new TypeBinding[length + 1], 0, length);
+ this.wrappers[length] = wrapper;
+ }
}
-String debugName() {
+public String debugName() {
return toString();
}
-ReferenceBinding resolve(LookupEnvironment environment) {
- if (resolvedType != null) return resolvedType;
-
- ReferenceBinding environmentType = fPackage.getType0(compoundName[compoundName.length - 1]);
- if (environmentType == this)
- environmentType = environment.askForType(compoundName);
- if (environmentType != null && environmentType != this) { // could not resolve any better, error was already reported against it
- resolvedType = environmentType;
- environment.updateArrayCache(this, environmentType);
- return environmentType; // when found, it replaces the unresolved type in the cache
+ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) {
+ ReferenceBinding targetType = this.resolvedType;
+ if (targetType == null) {
+ targetType = this.fPackage.getType0(this.compoundName[this.compoundName.length - 1]);
+ if (targetType == this)
+ targetType = environment.askForType(this.compoundName);
+ if (targetType != null && targetType != this) { // could not resolve any better, error was already reported against it
+ setResolvedType(targetType, environment);
+ } else {
+ environment.problemReporter.isClassPathCorrect(this.compoundName, null);
+ return null; // will not get here since the above error aborts the compilation
+ }
+ }
+ if (convertGenericToRawType) {
+ boolean rawEnclosing = false;
+ ReferenceBinding targetEnclosingType = targetType.enclosingType();
+ if (targetEnclosingType != null && targetEnclosingType.isGenericType()) { // convert to raw type since wasn't parameterized
+ rawEnclosing = true;
+ targetEnclosingType = environment.createRawType(targetEnclosingType, targetEnclosingType.enclosingType());
+ }
+ if (targetType.isGenericType()) { // raw reference to generic ?
+ return environment.createRawType(targetType, targetEnclosingType);
+ } else if (rawEnclosing) {
+ return environment.createParameterizedType(targetType, null, targetEnclosingType);
+ }
}
+ return targetType;
+}
+void setResolvedType(ReferenceBinding targetType, LookupEnvironment environment) {
+ if (this.resolvedType == targetType) return; // already resolved
- environment.problemReporter.isClassPathCorrect(compoundName, null);
- return null; // will not get here since the above error aborts the compilation
+ // targetType may be a source or binary type
+ this.resolvedType = targetType;
+ // must ensure to update any other type bindings that can contain the resolved type
+ // otherwise we could create 2 : 1 for this unresolved type & 1 for the resolved type
+ if (this.wrappers != null)
+ for (int i = 0, l = this.wrappers.length; i < l; i++)
+ this.wrappers[i].swapUnresolved(this, targetType, environment);
+ environment.updateCaches(this, targetType);
}
public String toString() {
return "Unresolved type " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index 2e06558..00bf26f 100644
--- a/src/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -13,32 +13,48 @@ package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.internal.compiler.impl.Constant;
public abstract class VariableBinding extends Binding {
+
public int modifiers;
public TypeBinding type;
public char[] name;
- public Constant constant;
+ private Constant constant;
public int id; // for flow-analysis (position in flowInfo bit vector)
+ public long tagBits;
-public boolean isConstantValue() {
- return constant != Constant.NotAConstant;
-}
-
-public final boolean isBlankFinal(){
- return (modifiers & AccBlankFinal) != 0;
-}
-/* Answer true if the receiver is final and cannot be changed
-*/
-
-public final boolean isFinal() {
- return (modifiers & AccFinal) != 0;
-}
-public char[] readableName() {
- return name;
-}
-public String toString() {
- String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
- s += " "; //$NON-NLS-1$
- s += (name != null) ? new String(name) : "UNNAMED FIELD"; //$NON-NLS-1$
- return s;
-}
+ public VariableBinding(char[] name, TypeBinding type, int modifiers, Constant constant) {
+ this.name = name;
+ this.type = type;
+ this.modifiers = modifiers;
+ this.constant = constant;
+ }
+
+ public Constant constant() {
+ return this.constant;
+ }
+
+ public final boolean isBlankFinal(){
+ return (modifiers & AccBlankFinal) != 0;
+ }
+ /* Answer true if the receiver is final and cannot be changed
+ */
+
+ public boolean isConstantValue() {
+ return constant != Constant.NotAConstant;
+ }
+
+ public final boolean isFinal() {
+ return (modifiers & AccFinal) != 0;
+ }
+ public char[] readableName() {
+ return name;
+ }
+ public void setConstant(Constant constant) {
+ this.constant = constant;
+ }
+ public String toString() {
+ String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
+ s += " "; //$NON-NLS-1$
+ s += (name != null) ? new String(name) : "UNNAMED FIELD"; //$NON-NLS-1$
+ return s;
+ }
}
diff --git a/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
new file mode 100644
index 0000000..5e7de03
--- /dev/null
+++ b/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2000-2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.util.Map;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+
+/*
+ * A wildcard acts as an argument for parameterized types, allowing to
+ * abstract parameterized types, e.g. List is not compatible with List,
+ * but compatible with List>.
+ */
+public class WildcardBinding extends ReferenceBinding {
+
+ ReferenceBinding genericType;
+ int rank;
+ public TypeBinding bound; // when unbound denotes the corresponding type variable (so as to retrieve its bound lazily)
+ char[] genericSignature;
+ public int kind;
+ ReferenceBinding superclass;
+ ReferenceBinding[] superInterfaces;
+ TypeVariableBinding typeVariable; // corresponding variable
+ LookupEnvironment environment;
+
+ /**
+ * When unbound, the bound denotes the corresponding type variable (so as to retrieve its bound lazily)
+ */
+ public WildcardBinding(ReferenceBinding genericType, int rank, TypeBinding bound, int kind, LookupEnvironment environment) {
+ this.genericType = genericType;
+ this.rank = rank;
+ this.kind = kind;
+ this.modifiers = AccPublic | AccGenericSignature; // treat wildcard as public
+ this.environment = environment;
+ initialize(genericType, bound);
+
+ if (genericType instanceof UnresolvedReferenceBinding)
+ ((UnresolvedReferenceBinding) genericType).addWrapper(this);
+ if (bound instanceof UnresolvedReferenceBinding)
+ ((UnresolvedReferenceBinding) bound).addWrapper(this);
+ }
+
+ public int kind() {
+ return WILDCARD_TYPE;
+ }
+
+ /**
+ * Returns true if the argument type satisfies all bounds of the type parameter
+ */
+ public boolean boundCheck(TypeBinding argumentType) {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return true;
+ case Wildcard.EXTENDS :
+ return argumentType.isCompatibleWith(this.bound);
+ default: // SUPER
+ // allowed as long as one is compatible with other (either way)
+ // ? super Exception ok for: IOException, since it would be ok for (Exception)ioException
+ return this.bound.isCompatibleWith(argumentType)
+ || argumentType.isCompatibleWith(this.bound);
+ }
+ }
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#canBeInstantiated()
+ */
+ public boolean canBeInstantiated() {
+ // cannot be asked per construction
+ return false;
+ }
+ /**
+ * Collect the substitutes into a map for certain type variables inside the receiver type
+ * e.g. Collection.findSubstitute(T, Collection>): T --> List
+ */
+ public void collectSubstitutes(TypeBinding otherType, Map substitutes) {
+
+ if (this.bound == null)
+ return;
+ if (otherType.isWildcard()) {
+ WildcardBinding otherWildcard = (WildcardBinding) otherType;
+ if (otherWildcard.bound != null) {
+ this.bound.collectSubstitutes(otherWildcard.bound, substitutes);
+ }
+ } else {
+ this.bound.collectSubstitutes(otherType, substitutes);
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#debugName()
+ */
+ public String debugName() {
+ return toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
+ */
+ public TypeBinding erasure() {
+ if (this.kind == Wildcard.EXTENDS)
+ return this.bound.erasure();
+ return typeVariable().erasure();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+ */
+ public char[] genericTypeSignature() {
+ if (this.genericSignature == null) {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ this.genericSignature = WILDCARD_STAR;
+ break;
+ case Wildcard.EXTENDS :
+ this.genericSignature = CharOperation.concat(WILDCARD_PLUS, this.bound.genericTypeSignature());
+ break;
+ default: // SUPER
+ this.genericSignature = CharOperation.concat(WILDCARD_MINUS, this.bound.genericTypeSignature());
+ }
+ }
+ return this.genericSignature;
+ }
+
+ public int hashCode() {
+ return this.genericType.hashCode();
+ }
+
+ void initialize(ReferenceBinding someGenericType, TypeBinding someBound) {
+ this.genericType = someGenericType;
+ this.bound = someBound;
+ if (someGenericType != null) {
+ this.fPackage = someGenericType.getPackage();
+ }
+ if (someBound != null) {
+ if (someBound.isTypeVariable())
+ this.tagBits |= HasTypeVariable;
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#isSuperclassOf(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
+ */
+ public boolean isSuperclassOf(ReferenceBinding otherType) {
+ if (this.kind == Wildcard.SUPER) {
+ if (this.bound instanceof ReferenceBinding) {
+ return ((ReferenceBinding) this.bound).isSuperclassOf(otherType);
+ } else { // array bound
+ return otherType.id == T_JavaLangObject;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the type is a wildcard
+ */
+ public boolean isUnboundWildcard() {
+ return this.kind == Wildcard.UNBOUND;
+ }
+
+ /**
+ * Returns true if the type is a wildcard
+ */
+ public boolean isWildcard() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName()
+ */
+ public char[] readableName() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return WILDCARD_NAME;
+ case Wildcard.EXTENDS :
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.readableName());
+ default: // SUPER
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.readableName());
+ }
+ }
+
+ ReferenceBinding resolve() {
+ BinaryTypeBinding.resolveType(this.genericType, this.environment, null, 0);
+ switch(this.kind) {
+ case Wildcard.EXTENDS :
+ case Wildcard.SUPER :
+ BinaryTypeBinding.resolveType(this.bound, this.environment, null, 0);
+ break;
+ case Wildcard.UNBOUND :
+ }
+ return this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+ */
+ public char[] shortReadableName() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return WILDCARD_NAME;
+ case Wildcard.EXTENDS :
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.shortReadableName());
+ default: // SUPER
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.shortReadableName());
+ }
+ }
+
+ /**
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#signature()
+ */
+ public char[] signature() {
+ // should not be called directly on a wildcard; signature should only be asked on
+ // original methods or type erasures (which cannot denote wildcards at first level)
+ if (this.signature == null) {
+ switch (this.kind) {
+ case Wildcard.EXTENDS :
+ return this.bound.signature();
+ default: // SUPER | UNBOUND
+ return this.typeVariable().signature();
+ }
+ }
+ return this.signature;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#sourceName()
+ */
+ public char[] sourceName() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return WILDCARD_NAME;
+ case Wildcard.EXTENDS :
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.sourceName());
+ default: // SUPER
+ return CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.sourceName());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding#superclass()
+ */
+ public ReferenceBinding superclass() {
+ if (this.superclass == null) {
+ TypeBinding superType = this.typeVariable().firstBound;
+ if (this.kind == Wildcard.EXTENDS) {
+ if (this.bound.isClass()) {
+ superType = this.bound;
+ }
+ }
+ this.superclass = superType != null && superType.isClass()
+ ? (ReferenceBinding) superType
+ : environment.getType(JAVA_LANG_OBJECT);
+ }
+
+ return this.superclass;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces()
+ */
+ public ReferenceBinding[] superInterfaces() {
+ if (this.superInterfaces == null) {
+ if (this.typeVariable() != null) {
+ this.superInterfaces = this.typeVariable.superInterfaces();
+ } else {
+ this.superInterfaces = NoSuperInterfaces;
+ }
+ if (this.kind == Wildcard.EXTENDS) {
+ if (this.bound.isInterface()) {
+ // augment super interfaces with the wildcard bound
+ int length = this.superInterfaces.length;
+ System.arraycopy(this.superInterfaces, 0, this.superInterfaces = new ReferenceBinding[length+1], 1, length);
+ this.superInterfaces[0] = (ReferenceBinding) this.bound; // make bound first
+ }
+ }
+ }
+ return this.superInterfaces;
+ }
+
+ public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
+ boolean affected = false;
+ if (this.genericType == unresolvedType) {
+ this.genericType = resolvedType; // no raw conversion
+ affected = true;
+ } else if (this.bound == unresolvedType) {
+ this.bound = resolvedType.isGenericType() ? env.createRawType(resolvedType, resolvedType.enclosingType()) : resolvedType;
+ affected = true;
+ }
+ if (affected)
+ initialize(this.genericType, this.bound);
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ switch (this.kind) {
+ case Wildcard.UNBOUND :
+ return new String(WILDCARD_NAME);
+ case Wildcard.EXTENDS :
+ return new String(CharOperation.concat(WILDCARD_NAME, WILDCARD_EXTENDS, this.bound.debugName().toCharArray()));
+ default: // SUPER
+ return new String(CharOperation.concat(WILDCARD_NAME, WILDCARD_SUPER, this.bound.debugName().toCharArray()));
+ }
+ }
+ /**
+ * Returns associated type variable, or null in case of inconsistency
+ */
+ public TypeVariableBinding typeVariable() {
+ if (this.typeVariable == null) {
+ TypeVariableBinding[] typeVariables = this.genericType.typeVariables();
+ if (this.rank < typeVariables.length)
+ this.typeVariable = typeVariables[this.rank];
+ }
+ return this.typeVariable;
+ }
+}
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
index ca99505..9b5dd5d 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
@@ -32,6 +32,22 @@ public abstract class AbstractCommentParser {
public static final char[] TAG_LINK = "link".toCharArray(); //$NON-NLS-1$
public static final char[] TAG_LINKPLAIN = "linkplain".toCharArray(); //$NON-NLS-1$
public static final char[] TAG_INHERITDOC = "inheritDoc".toCharArray(); //$NON-NLS-1$
+ public static final char[] TAG_VALUE = "value".toCharArray(); //$NON-NLS-1$
+
+ // tags value
+ public static final int NO_TAG_VALUE = 0;
+ public static final int TAG_DEPRECATED_VALUE = 1;
+ public static final int TAG_PARAM_VALUE = 2;
+ public static final int TAG_RETURN_VALUE = 3;
+ public static final int TAG_THROWS_VALUE = 4;
+ public static final int TAG_EXCEPTION_VALUE = 5;
+ public static final int TAG_SEE_VALUE = 6;
+ public static final int TAG_LINK_VALUE = 7;
+ public static final int TAG_LINKPLAIN_VALUE = 8;
+ public static final int TAG_INHERITDOC_VALUE = 9;
+ public static final int TAG_VALUE_VALUE = 10;
+ public static final int TAG_OTHERS_VALUE = 11;
+ protected int tagValue = NO_TAG_VALUE;
// tags expected positions
public final static int ORDERED_TAGS_NUMBER = 3;
@@ -43,26 +59,32 @@ public abstract class AbstractCommentParser {
public final static int COMPIL_PARSER = 0x00000001;
public final static int DOM_PARSER = 0x00000002;
- // Public fields
+ // Parse infos
public Scanner scanner;
+ public char[] source;
+ protected Parser sourceParser;
+ private int currentTokenType = -1;
+
+ // Options
public boolean checkDocComment = false;
+ public boolean reportProblems;
+ protected boolean jdk15;
- // Protected fields
+ // Results
protected boolean inherited, deprecated;
- protected char[] source;
+ protected Object returnStatement;
+
+ // Positions
protected int index, endComment, lineEnd;
protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition;
protected int textStart, memberStart;
protected int tagSourceStart, tagSourceEnd;
protected int inlineTagStart;
- protected Parser sourceParser;
- protected Object returnStatement;
- protected boolean lineStarted = false, inlineTagStarted = false;
- protected int kind;
protected int[] lineEnds;
- // Private fields
- private int currentTokenType = -1;
+ // Flags
+ protected boolean lineStarted = false, inlineTagStarted = false;
+ protected int kind;
// Line pointers
private int linePtr, lastLinePtr;
@@ -88,6 +110,7 @@ public abstract class AbstractCommentParser {
this.identifierLengthStack = new int[10];
this.astStack = new Object[30];
this.astLengthStack = new int[20];
+ this.reportProblems = sourceParser != null;
}
/* (non-Javadoc)
@@ -96,7 +119,7 @@ public abstract class AbstractCommentParser {
* If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc
* slot for being consumed later on.
*/
- protected boolean parseComment(int javadocStart, int javadocEnd) {
+ protected boolean commentParse(int javadocStart, int javadocEnd) {
boolean validComment = true;
try {
@@ -161,15 +184,14 @@ public abstract class AbstractCommentParser {
switch (nextCharacter) {
case '@' :
- boolean valid = false;
- // Start tag parsing only if we have a java identifier start character and if we are on line beginning or at inline tag beginning
+ // Start tag parsing only if we are on line beginning or at inline tag beginning
if ((!this.lineStarted || previousChar == '{')) {
this.lineStarted = true;
if (this.inlineTagStarted) {
this.inlineTagStarted = false;
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
// Cannot have @ inside inline comment
- if (this.sourceParser != null) {
+ if (this.reportProblems) {
int end = previousPosition, * chars and spaces are not allowed in tag names
- switch (pc) {
- case '}':
- case '!':
- case '#':
- case '%':
- case '&':
- case '\'':
- case ':':
- // case '-': allowed in tag names as this character is often used in doclets (bug 68087)
- case '<':
- case '>':
- case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
- break tagNameToken;
- default:
- if (pc == ' ' || Character.isWhitespace(pc)) break tagNameToken;
- }
- tk = readTokenAndConsume();
- pc = peekChar();
- }
- int length = this.tagSourceEnd-this.tagSourceStart+1;
- tag = new char[length];
- System.arraycopy(this.source, this.tagSourceStart, tag, 0, length);
- this.index = this.tagSourceEnd+1;
- this.scanner.currentPosition = this.tagSourceEnd+1;
- this.tagSourceStart = previousPosition;
- this.lineEnd = le;
- }
- switch (token) {
- case TerminalTokens.TokenNameIdentifier :
- if (CharOperation.equals(tag, TAG_DEPRECATED)) {
- this.deprecated = true;
- if (this.kind == DOM_PARSER) {
- valid = parseTag();
- } else {
- valid = true;
- }
- } else if (CharOperation.equals(tag, TAG_INHERITDOC)) {
- // inhibits inherited flag when tags have been already stored
- // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606
- // Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag
- // was encountered in comment. But it cannot be the case for COMPILER_PARSER
- // and so is enough as it is only this parser which signals the missing tag warnings...
- this.inherited = this.astPtr==-1;
- if (this.kind == DOM_PARSER) {
- valid = parseTag();
- } else {
- valid = true;
- }
- } else if (CharOperation.equals(tag, TAG_PARAM)) {
- valid = parseParam();
- } else if (CharOperation.equals(tag, TAG_EXCEPTION)) {
- valid = parseThrows(false);
- } else if (CharOperation.equals(tag, TAG_SEE)) {
- if (this.inlineTagStarted) {
- // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
- // Cannot have @see inside inline comment
- valid = false;
- if (this.sourceParser != null)
- this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
- } else {
- valid = parseSee(false);
- }
- } else if (CharOperation.equals(tag, TAG_LINK)) {
- if (this.inlineTagStarted) {
- valid = parseSee(false);
- } else {
- // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
- // Cannot have @link outside inline comment
- valid = false;
- if (this.sourceParser != null)
- this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
- }
- } else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
- if (this.inlineTagStarted) {
- valid = parseSee(true);
- } else {
- valid = parseTag();
- }
- } else {
- valid = parseTag();
- }
- break;
- case TerminalTokens.TokenNamereturn :
- valid = parseReturn();
- // verify characters after return tag (we're expecting text description)
- if(!verifyCharsAfterReturnTag(this.index)) {
- if (this.sourceParser != null) {
- int end = this.starPosition == -1 || this.lineEnd= this.endComment) end = invalidInlineTagLineEnd;
this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
@@ -466,38 +322,16 @@ public abstract class AbstractCommentParser {
protected abstract Object createFieldReference(Object receiver) throws InvalidInputException;
protected abstract Object createMethodReference(Object receiver, List arguments) throws InvalidInputException;
protected Object createReturnStatement() { return null; }
+ protected abstract void createTag();
protected abstract Object createTypeReference(int primitiveToken);
-
- private int getEndPosition() {
- if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) {
+
+ private int getIndexPosition() {
+ if (this.index > this.lineEnd) {
return this.lineEnd;
} else {
- return this.scanner.getCurrentTokenEndPosition();
- }
- }
-
- /*
- * Search the source position corresponding to the end of a given line number.
- * Warning: returned position is 1-based index!
- * @see Scanner#getLineEnd(int) We cannot directly use this method
- * when linePtr field is not initialized.
- *
- private int getLineEnd(int lineNumber) {
-
- if (this.scanner.linePtr != -1) {
- return this.scanner.getLineEnd(lineNumber);
+ return this.index-1;
}
- if (this.lineEnds == null)
- return -1;
- if (lineNumber > this.lineEnds.length+1)
- return -1;
- if (lineNumber <= 0)
- return -1;
- if (lineNumber == this.lineEnds.length + 1)
- return this.scanner.eofPosition;
- return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
}
- */
/**
* Search the line number corresponding to a specific position.
@@ -533,6 +367,14 @@ public abstract class AbstractCommentParser {
return m+2;
}
+ private int getTokenEndPosition() {
+ if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) {
+ return this.lineEnd;
+ } else {
+ return this.scanner.getCurrentTokenEndPosition();
+ }
+ }
+
/*
* Parse argument in @see tag method reference
*/
@@ -568,7 +410,7 @@ public abstract class AbstractCommentParser {
if (!verifySpaceOrEndComment()) {
int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
if (this.source[end]=='\n') end--;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
return null;
}
this.lineStarted = true;
@@ -638,7 +480,7 @@ public abstract class AbstractCommentParser {
if (!verifySpaceOrEndComment()) {
int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
if (this.source[end]=='\n') end--;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
return null;
}
// Create new argument
@@ -663,32 +505,48 @@ public abstract class AbstractCommentParser {
if (Character.toLowerCase(readChar()) == 'a') {
this.scanner.currentPosition = this.index;
if (readToken() == TerminalTokens.TokenNameIdentifier) {
- this.currentTokenType = -1; // do not update line end
+ consumeToken();
try {
if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'h', 'r', 'e', 'f'}, false) &&
readToken() == TerminalTokens.TokenNameEQUAL) {
- this.currentTokenType = -1; // do not update line end
+ consumeToken();
if (readToken() == TerminalTokens.TokenNameStringLiteral) {
- this.currentTokenType = -1; // do not update line end
+ consumeToken();
// Skip all characters after string literal until closing '>' (see bug 68726)
- while (this.index <= this.lineEnd && readToken() != TerminalTokens.TokenNameGREATER) {
+ while (readToken() != TerminalTokens.TokenNameGREATER) {
+ if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@' ||
+ (this.inlineTagStarted && this.scanner.currentCharacter == '}')) {
+ // Reset position: we want to rescan last token
+ this.index = this.tokenPreviousPosition;
+ this.scanner.currentPosition = this.tokenPreviousPosition;
+ this.currentTokenType = -1;
+ // Signal syntax error
+ if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+ }
+ return false;
+ }
this.currentTokenType = -1; // do not update line end
}
if (this.currentTokenType == TerminalTokens.TokenNameGREATER) {
consumeToken(); // update line end as new lines are allowed in URL description
while (readToken() != TerminalTokens.TokenNameLESS) {
- if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@') {
+ if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@' ||
+ (this.inlineTagStarted && this.scanner.currentCharacter == '}')) {
// Reset position: we want to rescan last token
this.index = this.tokenPreviousPosition;
this.scanner.currentPosition = this.tokenPreviousPosition;
this.currentTokenType = -1;
// Signal syntax error
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+ if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+ }
return false;
}
consumeToken();
}
- this.currentTokenType = -1; // do not update line end
+ consumeToken();
+ start = this.scanner.getCurrentTokenStartPosition();
if (readChar() == '/') {
if (Character.toLowerCase(readChar()) == 'a') {
if (readChar() == '>') {
@@ -710,7 +568,9 @@ public abstract class AbstractCommentParser {
this.scanner.currentPosition = this.tokenPreviousPosition;
this.currentTokenType = -1;
// Signal syntax error
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+ if (this.tagValue != TAG_VALUE_VALUE) { // do not report error for @value tag, this will be done after...
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd);
+ }
return false;
}
@@ -723,7 +583,7 @@ public abstract class AbstractCommentParser {
this.identifierLengthPtr = -1;
int start = this.scanner.getCurrentTokenStartPosition();
this.memberStart = start;
-
+
// Get member identifier
if (readToken() == TerminalTokens.TokenNameIdentifier) {
consumeToken();
@@ -740,28 +600,28 @@ public abstract class AbstractCommentParser {
this.scanner.getCurrentTokenEndPosition() :
this.scanner.getCurrentTokenStartPosition();
end = end < this.lineEnd ? end : this.lineEnd;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
}
return null;
}
-
+
// Reset position: we want to rescan last token
this.index = previousPosition;
this.scanner.currentPosition = previousPosition;
this.currentTokenType = -1;
-
+
// Verify character(s) after identifier (expecting space or end comment)
if (!verifySpaceOrEndComment()) {
int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
if (this.source[end]=='\n') end--;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
return null;
}
return createFieldReference(receiver);
}
- int end = getEndPosition() - 1;
+ int end = getTokenEndPosition() - 1;
end = start > end ? start : end;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, end);
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(start, end);
// Reset position: we want to rescan last token
this.index = this.tokenPreviousPosition;
this.scanner.currentPosition = this.tokenPreviousPosition;
@@ -772,38 +632,201 @@ public abstract class AbstractCommentParser {
/*
* Parse @param tag declaration
*/
- protected boolean parseParam() {
+ protected boolean parseParam() throws InvalidInputException {
- // Store current token state
+ // Store current state
int start = this.tagSourceStart;
int end = this.tagSourceEnd;
-
- try {
- // Push identifier next
- int token = readToken();
+ boolean tokenWhiteSpace = this.scanner.tokenizeWhiteSpace;
+ this.scanner.tokenizeWhiteSpace = true;
+// this.scanner.tokenizeLineSeparator = true;
+
+ // Verify that there are whitespaces after tag
+ int token = readToken();
+ if (token != TerminalTokens.TokenNameWHITESPACE) {
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(start, this.scanner.getCurrentTokenEndPosition());
+ this.scanner.currentPosition = start;
+ this.index = start;
+ this.currentTokenType = -1;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+ return false;
+ }
+
+ // Get first non whitespace token
+ this.identifierPtr = -1;
+ this.identifierLengthPtr = -1;
+ boolean hasMultiLines = this.scanner.currentPosition > (this.lineEnd+1);
+ boolean isTypeParam = false;
+ boolean valid = true, empty = true;
+ nextToken: while (true) {
+ this.currentTokenType = -1;
+ try {
+ token = readToken();
+ } catch (InvalidInputException e) {
+ valid = false;
+ }
switch (token) {
case TerminalTokens.TokenNameIdentifier :
- consumeToken();
- return pushParamName();
- case TerminalTokens.TokenNameEOF :
- break;
- default :
- start = this.scanner.getCurrentTokenStartPosition();
- end = getEndPosition();
- if (end < start) start = this.tagSourceStart;
- break;
+ if (valid) {
+ // store param name id
+ pushIdentifier(true);
+ start = this.scanner.getCurrentTokenStartPosition();
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ break nextToken;
+ }
+ // fall through next case to report error
+ case TerminalTokens.TokenNameLESS:
+ if (valid && this.jdk15) {
+ // store '<' in identifiers stack as we need to add it to tag element (bug 79809)
+ pushIdentifier(true);
+ start = this.scanner.getCurrentTokenStartPosition();
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ isTypeParam = true;
+ break nextToken;
+ }
+ // fall through next case to report error
+ default:
+ if (token == TerminalTokens.TokenNameLEFT_SHIFT) isTypeParam = true;
+ if (valid && !hasMultiLines) start = this.scanner.getCurrentTokenStartPosition();
+ valid = false;
+ if (!hasMultiLines) {
+ empty = false;
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ break;
+ }
+ end = this.lineEnd;
+ // when several lines, fall through next case to report problem immediately
+ case TerminalTokens.TokenNameWHITESPACE:
+ if (this.scanner.currentPosition > (this.lineEnd+1)) hasMultiLines = true;
+ if (valid) break;
+ // if not valid fall through next case to report error
+ case TerminalTokens.TokenNameEOF:
+ if (this.reportProblems)
+ if (empty)
+ this.sourceParser.problemReporter().javadocMissingParamName(start, end, this.sourceParser.modifiers);
+ else if (this.jdk15 && isTypeParam)
+ this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+ else
+ this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end);
+ this.scanner.currentPosition = start;
+ this.index = start;
+ this.currentTokenType = -1;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+ return false;
}
- } catch (InvalidInputException e) {
- end = getEndPosition();
}
-
- // Reset position to avoid missing tokens when new line was encountered
- this.index = this.tokenPreviousPosition;
- this.scanner.currentPosition = this.tokenPreviousPosition;
- this.currentTokenType = -1;
-
+
+ // Scan more tokens for type parameter declaration
+ if (isTypeParam && this.jdk15) {
+ // Get type parameter name
+ nextToken: while (true) {
+ this.currentTokenType = -1;
+ try {
+ token = readToken();
+ } catch (InvalidInputException e) {
+ valid = false;
+ }
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ if (valid && this.scanner.currentPosition <= (this.lineEnd+1)) break;
+ // if not valid fall through next case to report error
+ case TerminalTokens.TokenNameEOF:
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+ this.scanner.currentPosition = start;
+ this.index = start;
+ this.currentTokenType = -1;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+ return false;
+ case TerminalTokens.TokenNameIdentifier :
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ if (valid) {
+ // store param name id
+ pushIdentifier(false);
+ break nextToken;
+ }
+ break;
+ default:
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ valid = false;
+ break;
+ }
+ }
+
+ // Get last character of type parameter declaration
+ boolean spaces = false;
+ nextToken: while (true) {
+ this.currentTokenType = -1;
+ try {
+ token = readToken();
+ } catch (InvalidInputException e) {
+ valid = false;
+ }
+ switch (token) {
+ case TerminalTokens.TokenNameWHITESPACE:
+ if (this.scanner.currentPosition > (this.lineEnd+1)) {
+ // do not accept type parameter declaration on several lines
+ hasMultiLines = true;
+ valid = false;
+ }
+ spaces = true;
+ if (valid) break;
+ // if not valid fall through next case to report error
+ case TerminalTokens.TokenNameEOF:
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+ this.scanner.currentPosition = start;
+ this.index = start;
+ this.currentTokenType = -1;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+ return false;
+ case TerminalTokens.TokenNameGREATER:
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ if (valid) {
+ // store '>' in identifiers stack as we need to add it to tag element (bug 79809)
+ pushIdentifier(false);
+ break nextToken;
+ }
+ break;
+ default:
+ if (!spaces) end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ // Verify that tag name is well followed by white spaces
+ if (valid) {
+ this.currentTokenType = -1;
+ int restart = this.scanner.currentPosition;
+ try {
+ token = readToken();
+ } catch (InvalidInputException e) {
+ valid = false;
+ }
+ if (token == TerminalTokens.TokenNameWHITESPACE) {
+ this.scanner.currentPosition = restart;
+ this.index = restart;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
+ return pushParamName(isTypeParam);
+ }
+ }
+
// Report problem
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingParamName(start, end);
+ this.currentTokenType = -1;
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ while (readToken() != TerminalTokens.TokenNameWHITESPACE) {
+ this.currentTokenType = -1;
+ end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
+ }
+ if (this.reportProblems)
+ if (this.jdk15 && isTypeParam)
+ this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
+ else
+ this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end);
+ this.scanner.currentPosition = start;
+ this.index = start;
+ this.currentTokenType = -1;
+ this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
return false;
}
@@ -884,36 +907,27 @@ public abstract class AbstractCommentParser {
/*
* Parse a reference in @see tag
*/
- protected boolean parseReference(boolean plain) throws InvalidInputException {
- Object typeRef = null;
- Object reference = null;
- int previousPosition = -1;
- int typeRefStartPosition = -1;
- nextToken : while (this.index < this.scanner.eofPosition) {
- previousPosition = this.index;
- int token = readToken();
- switch (token) {
- case TerminalTokens.TokenNameStringLiteral : // @see "string"
- int start = this.scanner.getCurrentTokenStartPosition();
- consumeToken();
- // If typeRef != null we may raise a warning here to let user know there's an unused reference...
- // Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302)
- if (typeRef != null) {
- start = this.tagSourceEnd+1;
- previousPosition = start;
- typeRef = null;
- }
- // verify end line (expecting empty or end comment)
- if (verifyEndLine(previousPosition)) {
- return true;
- }
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
- return false;
- case TerminalTokens.TokenNameLESS : // @see "label
- consumeToken();
- start = this.scanner.getCurrentTokenStartPosition();
- if (parseHref()) {
+ protected boolean parseReference() throws InvalidInputException {
+ int currentPosition = this.scanner.currentPosition;
+ try {
+ Object typeRef = null;
+ Object reference = null;
+ int previousPosition = -1;
+ int typeRefStartPosition = -1;
+
+ // Get reference tokens
+ nextToken : while (this.index < this.scanner.eofPosition) {
+ previousPosition = this.index;
+ int token = readToken();
+ switch (token) {
+ case TerminalTokens.TokenNameStringLiteral : // @see "string"
consumeToken();
+ int start = this.scanner.getCurrentTokenStartPosition();
+ if (this.tagValue == TAG_VALUE_VALUE) {
+ // String reference are not allowed for @value tag
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getTokenEndPosition(), this.sourceParser.modifiers);
+ return false;
+ }
// If typeRef != null we may raise a warning here to let user know there's an unused reference...
// Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302)
if (typeRef != null) {
@@ -921,87 +935,109 @@ public abstract class AbstractCommentParser {
previousPosition = start;
typeRef = null;
}
- // verify end line (expecting empty or end comment)
+ // verify end line
if (verifyEndLine(previousPosition)) {
return true;
}
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd);
- }
- return false;
- case TerminalTokens.TokenNameERROR :
- if (this.scanner.currentCharacter == '#') { // @see ...#member
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedText(this.scanner.currentPosition, this.lineEnd);
+ return false;
+ case TerminalTokens.TokenNameLESS : // @see "label
consumeToken();
- reference = parseMember(typeRef);
- if (reference != null) {
- return pushSeeRef(reference, plain);
+ start = this.scanner.getCurrentTokenStartPosition();
+ if (parseHref()) {
+ consumeToken();
+ // If typeRef != null we may raise a warning here to let user know there's an unused reference...
+ // Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302)
+ if (typeRef != null) {
+ start = this.tagSourceEnd+1;
+ previousPosition = start;
+ typeRef = null;
+ }
+ if (this.tagValue == TAG_VALUE_VALUE) {
+ // String reference are not allowed for @value tag
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getIndexPosition(), this.sourceParser.modifiers);
+ return false;
+ }
+ // verify end line
+ if (verifyEndLine(previousPosition)) return true;
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocUnexpectedText(this.scanner.currentPosition, this.lineEnd);
+ }
+ else if (this.tagValue == TAG_VALUE_VALUE) {
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidValueReference(start, getIndexPosition(), this.sourceParser.modifiers);
}
return false;
- }
- break nextToken;
- case TerminalTokens.TokenNameIdentifier :
- if (typeRef == null) {
- typeRefStartPosition = this.scanner.getCurrentTokenStartPosition();
- typeRef = parseQualifiedName(true);
- break;
- }
- break nextToken;
- default :
- break nextToken;
+ case TerminalTokens.TokenNameERROR :
+ if (this.scanner.currentCharacter == '#') { // @see ...#member
+ consumeToken();
+ reference = parseMember(typeRef);
+ if (reference != null) {
+ return pushSeeRef(reference);
+ }
+ return false;
+ }
+ break nextToken;
+ case TerminalTokens.TokenNameIdentifier :
+ if (typeRef == null) {
+ typeRefStartPosition = this.scanner.getCurrentTokenStartPosition();
+ typeRef = parseQualifiedName(true);
+ break;
+ }
+ default :
+ break nextToken;
+ }
}
- }
-
- // Verify that we got a reference
- if (reference == null) reference = typeRef;
- if (reference == null) {
- this.index = this.tokenPreviousPosition;
- this.scanner.currentPosition = this.tokenPreviousPosition;
- this.currentTokenType = -1;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingSeeReference(this.tagSourceStart, this.tagSourceEnd);
- return false;
- }
- // Reset position at the end of type reference
- this.index = this.lastIdentifierEndPosition+1;
- this.scanner.currentPosition = this.index;
- this.currentTokenType = -1;
-
- // Verify that line end does not start with an open parenthese (which could be a constructor reference wrongly written...)
- // See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=47215
- char ch = peekChar();
- if (ch == '(') {
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(typeRefStartPosition, this.lineEnd);
- return false;
- }
+ // Verify that we got a reference
+ if (reference == null) reference = typeRef;
+ if (reference == null) {
+ this.index = this.tokenPreviousPosition;
+ this.scanner.currentPosition = this.tokenPreviousPosition;
+ this.currentTokenType = -1;
+ if (this.tagValue == TAG_VALUE_VALUE) {
+ if (this.kind == DOM_PARSER) createTag();
+ return true;
+ }
+ if (this.reportProblems) {
+ this.sourceParser.problemReporter().javadocMissingReference(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers);
+ }
+ return false;
+ }
- // Verify that we get white space after reference
- if (!verifySpaceOrEndComment()) {
- this.index = this.tokenPreviousPosition;
- this.scanner.currentPosition = this.tokenPreviousPosition;
+ // Reset position at the end of type reference
+ this.index = this.lastIdentifierEndPosition+1;
+ this.scanner.currentPosition = this.index;
this.currentTokenType = -1;
- int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
- if (this.source[end]=='\n') end--;
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(typeRefStartPosition, end);
- return false;
- }
-
- // Everything is OK, store reference
- return pushSeeRef(reference, plain);
- }
- /*
- * Parse @return tag declaration
- */
- protected abstract boolean parseReturn();
+ // In case of @value, we have an invalid reference (only static field refs are valid for this tag)
+ if (this.tagValue == TAG_VALUE_VALUE) {
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(typeRefStartPosition, this.lineEnd);
+ return false;
+ }
- /*
- * Parse @see tag declaration
- */
- protected boolean parseSee(boolean plain) {
- int start = this.scanner.currentPosition;
- try {
- return parseReference(plain);
- } catch (InvalidInputException ex) {
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, getEndPosition());
+ // Verify that line end does not start with an open parenthese (which could be a constructor reference wrongly written...)
+ // See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=47215
+ char ch = peekChar();
+ if (ch == '(') {
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocMissingHashCharacter(typeRefStartPosition, this.lineEnd, String.valueOf(this.source, typeRefStartPosition, this.lineEnd-typeRefStartPosition+1));
+ return false;
+ }
+
+ // Verify that we get white space after reference
+ if (!verifySpaceOrEndComment()) {
+ this.index = this.tokenPreviousPosition;
+ this.scanner.currentPosition = this.tokenPreviousPosition;
+ this.currentTokenType = -1;
+ int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+ if (this.source[end]=='\n') end--;
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocMalformedSeeReference(typeRefStartPosition, end);
+ return false;
+ }
+
+ // Everything is OK, store reference
+ return pushSeeRef(reference);
+ }
+ catch (InvalidInputException ex) {
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidReference(currentPosition, getTokenEndPosition());
}
// Reset position to avoid missing tokens when new line was encountered
this.index = this.tokenPreviousPosition;
@@ -1011,24 +1047,25 @@ public abstract class AbstractCommentParser {
}
/*
- * Parse @return tag declaration
+ * Parse tag declaration
*/
- protected abstract boolean parseTag();
+ protected abstract boolean parseTag(int previousPosition) throws InvalidInputException;
/*
* Parse @throws tag declaration
*/
- protected boolean parseThrows(boolean real) {
+ protected boolean parseThrows() {
int start = this.scanner.currentPosition;
try {
Object typeRef = parseQualifiedName(true);
if (typeRef == null) {
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd);
+ if (this.reportProblems)
+ this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd, this.sourceParser.modifiers);
} else {
- return pushThrowName(typeRef, real);
+ return pushThrowName(typeRef);
}
} catch (InvalidInputException ex) {
- if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getEndPosition());
+ if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getTokenEndPosition());
}
return false;
}
@@ -1036,7 +1073,7 @@ public abstract class AbstractCommentParser {
/*
* Return current character without move index position.
*/
- private char peekChar() {
+ protected char peekChar() {
int idx = this.index;
char c = this.source[idx++];
if (c == '\\' && this.source[idx] == 'u') {
@@ -1124,12 +1161,12 @@ public abstract class AbstractCommentParser {
/*
* Push a param name in ast node stack.
*/
- protected abstract boolean pushParamName();
+ protected abstract boolean pushParamName(boolean isTypeParam);
/*
* Push a reference statement in ast node stack.
*/
- protected abstract boolean pushSeeRef(Object statement, boolean plain);
+ protected abstract boolean pushSeeRef(Object statement);
/*
* Push a text element in ast node stack
@@ -1139,7 +1176,7 @@ public abstract class AbstractCommentParser {
/*
* Push a throws type ref in ast node stack.
*/
- protected abstract boolean pushThrowName(Object typeRef, boolean real);
+ protected abstract boolean pushThrowName(Object typeRef);
/*
* Read current character and move index position.
@@ -1185,7 +1222,7 @@ public abstract class AbstractCommentParser {
return this.currentTokenType;
}
- private int readTokenAndConsume() throws InvalidInputException {
+ protected int readTokenAndConsume() throws InvalidInputException {
int token = readToken();
consumeToken();
return token;
@@ -1273,6 +1310,19 @@ public abstract class AbstractCommentParser {
* Note that end of comment may be preceeding by several contiguous '*' chars.
*/
private boolean verifyEndLine(int textPosition) {
+ // Special case for inline tag
+ if (this.inlineTagStarted) {
+ // expecting closing brace
+ if (peekChar() == '}') {
+ if (this.kind == DOM_PARSER) {
+ createTag();
+ pushText(textPosition, this.starPosition);
+ }
+ return true;
+ }
+ return false;
+ }
+
int startPosition = this.index;
int previousPosition = this.index;
this.starPosition = -1;
@@ -1282,7 +1332,7 @@ public abstract class AbstractCommentParser {
case '\r':
case '\n':
if (this.kind == DOM_PARSER) {
- parseTag();
+ createTag();
pushText(textPosition, previousPosition);
}
this.index = previousPosition;
@@ -1298,7 +1348,7 @@ public abstract class AbstractCommentParser {
case '/':
if (this.starPosition >= textPosition) {
if (this.kind == DOM_PARSER) {
- parseTag();
+ createTag();
pushText(textPosition, this.starPosition);
}
return true;
@@ -1316,45 +1366,6 @@ public abstract class AbstractCommentParser {
}
/*
- * Verify that some text exists after a @return tag. Text must be different than
- * end of comment which may be preceeding by several '*' chars.
- */
- private boolean verifyCharsAfterReturnTag(int startPosition) {
- // Whitespace or inline tag closing brace
- int previousPosition = this.index;
- char ch = readChar();
- boolean malformed = true;
- while (Character.isWhitespace(ch)) {
- malformed = false;
- previousPosition = this.index;
- ch = readChar();
- }
- // End of comment
- this.starPosition = -1;
- nextChar: while (this.index= startPosition) { // valid only if a star was previous character
- return false;
- }
- default :
- // valid if any other character is encountered, even white spaces
- this.index = startPosition;
- return !malformed;
-
- }
- previousPosition = this.index;
- ch = readChar();
- }
- this.index = startPosition;
- return false;
- }
-
- /*
* Verify characters after a name matches one of following conditions:
* 1- first character is a white space
* 2- first character is a closing brace *and* we're currently parsing an inline tag
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/src/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
index 7786636..4d4c63b 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
@@ -14,20 +14,8 @@ import java.util.List;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
-import org.eclipse.jdt.internal.compiler.ast.ImplicitDocTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.Javadoc;
-import org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArgumentExpression;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArrayQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocArraySingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
-import org.eclipse.jdt.internal.compiler.ast.JavadocQualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocSingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -41,12 +29,16 @@ public class JavadocParser extends AbstractCommentParser {
// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
// Store param references for tag with invalid syntax
- private int invParamsPtr = -1;
- private JavadocSingleNameReference[] invParamsStack;
+ private int invalidParamReferencesPtr = -1;
+ private ASTNode[] invalidParamReferencesStack;
- JavadocParser(Parser sourceParser) {
+ // Store current tag stack pointer
+ private int currentAstPtr= -2;
+
+ public JavadocParser(Parser sourceParser) {
super(sourceParser);
this.checkDocComment = this.sourceParser.options.docCommentSupport;
+ this.jdk15 = this.sourceParser.options.sourceLevel >= ClassFileConstants.JDK1_5;
this.kind = COMPIL_PARSER;
}
@@ -68,7 +60,7 @@ public class JavadocParser extends AbstractCommentParser {
this.scanner.linePtr = this.sourceParser.scanner.linePtr;
this.lineEnds = this.scanner.lineEnds;
this.docComment = new Javadoc(javadocStart, javadocEnd);
- parseComment(javadocStart, javadocEnd);
+ commentParse(javadocStart, javadocEnd);
} else {
// Init javadoc if necessary
if (this.sourceParser.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore) {
@@ -93,12 +85,13 @@ public class JavadocParser extends AbstractCommentParser {
nextCharacter : while (this.index < this.lineEnd) {
char c = readChar(); // consider unicodes
switch (c) {
- default :
- if (Character.isWhitespace(c)) {
- continue nextCharacter;
- }
- break;
- case '*' :
+ case '*' :
+ case '\u000c' : /* FORM FEED */
+ case ' ' : /* SPACE */
+ case '\t' : /* HORIZONTAL TABULATION */
+ case '\n' : /* LINE FEED */
+ case '\r' : /* CR */
+ // do nothing for space or '*' characters
continue nextCharacter;
case '@' :
if ((readChar() == 'd') && (readChar() == 'e') &&
@@ -173,10 +166,11 @@ public class JavadocParser extends AbstractCommentParser {
field.receiver = typeRef;
field.tagSourceStart = this.tagSourceStart;
field.tagSourceEnd = this.tagSourceEnd;
+ field.tagValue = this.tagValue;
return field;
}
catch (ClassCastException ex) {
- throw new InvalidInputException();
+ throw new InvalidInputException();
}
}
/* (non-Javadoc)
@@ -207,12 +201,14 @@ public class JavadocParser extends AbstractCommentParser {
// Create node
if (arguments == null) {
if (isConstructor) {
- JavadocAllocationExpression expr = new JavadocAllocationExpression(this.identifierPositionStack[0]);
- expr.type = typeRef;
- return expr;
+ JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+ alloc.type = typeRef;
+ alloc.tagValue = this.tagValue;
+ return alloc;
} else {
JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0]);
msg.receiver = typeRef;
+ msg.tagValue = this.tagValue;
return msg;
}
} else {
@@ -222,10 +218,12 @@ public class JavadocParser extends AbstractCommentParser {
JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
alloc.arguments = expressions;
alloc.type = typeRef;
+ alloc.tagValue = this.tagValue;
return alloc;
} else {
JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0], expressions);
msg.receiver = typeRef;
+ msg.tagValue = this.tagValue;
return msg;
}
}
@@ -271,6 +269,7 @@ public class JavadocParser extends AbstractCommentParser {
protected boolean parseReturn() {
if (this.returnStatement == null) {
this.returnStatement = createReturnStatement();
+ this.currentAstPtr = this.astPtr;
return true;
}
if (this.sourceParser != null) this.sourceParser.problemReporter().javadocDuplicatedReturnTag(
@@ -279,45 +278,185 @@ public class JavadocParser extends AbstractCommentParser {
return false;
}
- /*
- * Parse @return tag declaration
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
*/
- protected boolean parseTag() {
- return true;
+ protected boolean parseTag(int previousPosition) throws InvalidInputException {
+ boolean valid = false;
+
+ // In case of previous return tag, set it to not empty if parsing an inline tag
+ if (this.currentAstPtr != -2 && this.returnStatement != null) {
+ this.currentAstPtr = -2;
+ JavadocReturnStatement javadocReturn = (JavadocReturnStatement) this.returnStatement;
+ javadocReturn.empty = javadocReturn.empty && !this.inlineTagStarted;
+ }
+
+ // Read tag name
+ int token = readTokenAndConsume();
+ this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+ this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+ char[] tag = this.scanner.getCurrentIdentifierSource(); // first token is either an identifier or a keyword
+
+ // Decide which parse to perform depending on tag name
+ this.tagValue = NO_TAG_VALUE;
+ switch (token) {
+ case TerminalTokens.TokenNameIdentifier :
+ switch (tag[0]) {
+ case 'd':
+ if (CharOperation.equals(tag, TAG_DEPRECATED)) {
+ this.deprecated = true;
+ valid = true;
+ this.tagValue = TAG_DEPRECATED_VALUE;
+ }
+ break;
+ case 'i':
+ if (CharOperation.equals(tag, TAG_INHERITDOC)) {
+ // inhibits inherited flag when tags have been already stored
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606
+ // Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag
+ // was encountered in comment. But it cannot be the case for COMPILER_PARSER
+ // and so is enough as it is only this parser which signals the missing tag warnings...
+ this.inherited = this.astPtr==-1;
+ valid = true;
+ this.tagValue = TAG_INHERITDOC_VALUE;
+ }
+ break;
+ case 'p':
+ if (CharOperation.equals(tag, TAG_PARAM)) {
+ this.tagValue = TAG_PARAM_VALUE;
+ valid = parseParam();
+ }
+ break;
+ case 'e':
+ if (CharOperation.equals(tag, TAG_EXCEPTION)) {
+ this.tagValue = TAG_EXCEPTION_VALUE;
+ valid = parseThrows();
+ }
+ break;
+ case 's':
+ if (CharOperation.equals(tag, TAG_SEE)) {
+ if (this.inlineTagStarted) {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @see inside inline comment
+ valid = false;
+ if (this.sourceParser != null)
+ this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+ } else {
+ this.tagValue = TAG_SEE_VALUE;
+ valid = parseReference();
+ }
+ }
+ break;
+ case 'l':
+ if (CharOperation.equals(tag, TAG_LINK)) {
+ this.tagValue = TAG_LINK_VALUE;
+ if (this.inlineTagStarted) {
+ valid= parseReference();
+ } else {
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+ // Cannot have @link outside inline comment
+ valid = false;
+ if (this.sourceParser != null)
+ this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+ }
+ } else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
+ this.tagValue = TAG_LINKPLAIN_VALUE;
+ if (this.inlineTagStarted) {
+ valid = parseReference();
+ } else {
+ valid = false;
+ if (this.sourceParser != null)
+ this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+ }
+ }
+ break;
+ case 'v':
+ if (this.jdk15 && CharOperation.equals(tag, TAG_VALUE)) {
+ this.tagValue = TAG_VALUE_VALUE;
+ if (this.inlineTagStarted) {
+ valid = parseReference();
+ } else {
+ valid = false;
+ if (this.sourceParser != null)
+ this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+ }
+ } else {
+ createTag();
+ }
+ break;
+ }
+ break;
+ case TerminalTokens.TokenNamereturn :
+ this.tagValue = TAG_RETURN_VALUE;
+ valid = parseReturn();
+ /* verify characters after return tag (we're expecting text description)
+ if(!verifyCharsAfterReturnTag(this.index)) {
+ if (this.sourceParser != null) {
+ int end = this.starPosition == -1 || this.lineEnd= stackLength) {
- System.arraycopy(
- this.invParamsStack, 0,
- this.invParamsStack = new JavadocSingleNameReference[stackLength + AstStackIncrement], 0,
- stackLength);
+ if (!isTypeParam) { // do not verify for type parameters as @throws may be invalid tag (when declared in class)
+ for (int i=THROWS_TAG_EXPECTED_ORDER; i<=this.astLengthPtr; i+=ORDERED_TAGS_NUMBER) {
+ if (this.astLengthStack[i] != 0) {
+ if (this.sourceParser != null) this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
+ // store invalid param references in specific array
+ if (this.invalidParamReferencesPtr == -1l) {
+ this.invalidParamReferencesStack = new JavadocSingleNameReference[10];
+ }
+ int stackLength = this.invalidParamReferencesStack.length;
+ if (++this.invalidParamReferencesPtr >= stackLength) {
+ System.arraycopy(
+ this.invalidParamReferencesStack, 0,
+ this.invalidParamReferencesStack = new JavadocSingleNameReference[stackLength + AstStackIncrement], 0,
+ stackLength);
+ }
+ this.invalidParamReferencesStack[this.invalidParamReferencesPtr] = nameRef;
+ return false;
}
- this.invParamsStack[this.invParamsPtr] = nameRef;
- return false;
}
}
switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
@@ -339,7 +478,7 @@ public class JavadocParser extends AbstractCommentParser {
/*
* Push a reference statement in ast node stack.
*/
- protected boolean pushSeeRef(Object statement, boolean plain) {
+ protected boolean pushSeeRef(Object statement) {
if (this.astLengthPtr == -1) { // First push
pushOnAstStack(null, true);
pushOnAstStack(null, true);
@@ -370,13 +509,40 @@ public class JavadocParser extends AbstractCommentParser {
* @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
*/
protected void pushText(int start, int end) {
- // compiler does not matter of text
+ // In case of previous return tag, verify that text make it not empty
+ if (this.currentAstPtr != -2 && this.returnStatement != null) {
+ int position = this.index;
+ this.index = start;
+ boolean empty = true;
+ boolean star = false;
+ char ch = readChar();
+ // Look for first character other than white or '*'
+ if (Character.isWhitespace(ch) || start>(this.tagSourceEnd+1)) {
+ while (this.index <= end && empty) {
+ if (!star) {
+ empty = Character.isWhitespace(ch) || ch == '*';
+ star = ch == '*';
+ } else if (ch != '*') {
+ empty = false;
+ break;
+ }
+ ch = readChar();
+ }
+ }
+ // Store result in previous return tag
+ ((JavadocReturnStatement)this.returnStatement).empty = empty;
+ // Reset position and current ast ptr if we are on a different tag than previous return one
+ this.index = position;
+ if (this.currentAstPtr != this.astPtr) {
+ this.currentAstPtr = -2;
+ }
+ }
}
/*
* Push a throws type ref in ast node stack.
*/
- protected boolean pushThrowName(Object typeRef, boolean real) {
+ protected boolean pushThrowName(Object typeRef) {
if (this.astLengthPtr == -1) { // First push
pushOnAstStack(null, true);
pushOnAstStack(typeRef, true);
@@ -416,9 +582,9 @@ public class JavadocParser extends AbstractCommentParser {
}
// Copy array of invalid syntax param tags
- if (this.invParamsPtr >= 0) {
- this.docComment.invalidParameters = new JavadocSingleNameReference[this.invParamsPtr+1];
- System.arraycopy(this.invParamsStack, 0, this.docComment.invalidParameters, 0, this.invParamsPtr+1);
+ if (this.invalidParamReferencesPtr >= 0) {
+ this.docComment.invalidParameters = new JavadocSingleNameReference[this.invalidParamReferencesPtr+1];
+ System.arraycopy(this.invalidParamReferencesStack, 0, this.docComment.invalidParameters, 0, this.invalidParamReferencesPtr+1);
}
// If no nodes stored return
@@ -431,36 +597,56 @@ public class JavadocParser extends AbstractCommentParser {
for (int i=0; i<=this.astLengthPtr; i++) {
sizes[i%ORDERED_TAGS_NUMBER] += this.astLengthStack[i];
}
- this.docComment.references = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]];
- this.docComment.thrownExceptions = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]];
- this.docComment.parameters = new JavadocSingleNameReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+ this.docComment.seeReferences = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]];
+ this.docComment.exceptionReferences = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]];
+ this.docComment.paramReferences = new JavadocSingleNameReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+ int paramRefPtr = sizes[PARAM_TAG_EXPECTED_ORDER];
+ this.docComment.paramTypeParameters = new JavadocSingleTypeReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+ int paramTypeParamPtr = sizes[PARAM_TAG_EXPECTED_ORDER];
// Store nodes in arrays
while (this.astLengthPtr >= 0) {
int ptr = this.astLengthPtr % ORDERED_TAGS_NUMBER;
// Starting with the stack top, so get references (eg. Expression) coming from @see declarations
- if (ptr == SEE_TAG_EXPECTED_ORDER) {
- int size = this.astLengthStack[this.astLengthPtr--];
- for (int i=0; i resize arrays
+ int size = sizes[PARAM_TAG_EXPECTED_ORDER];
+ System.arraycopy(this.docComment.paramReferences, paramRefPtr, this.docComment.paramReferences = new JavadocSingleNameReference[size - paramRefPtr], 0, size - paramRefPtr);
+ System.arraycopy(this.docComment.paramTypeParameters, paramTypeParamPtr, this.docComment.paramTypeParameters = new JavadocSingleTypeReference[size - paramTypeParamPtr], 0, size - paramTypeParamPtr);
+ }
}
}
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/Parser.java b/src/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 81fd8d4..cedccfe 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -24,10 +24,12 @@ import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
@@ -36,119 +38,151 @@ import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.Util;
-public class Parser implements BindingIds, ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
- protected ProblemReporter problemReporter;
- protected CompilerOptions options;
- public int firstToken ; // handle for multiple parsing goals
- public int lastAct ; //handle for multiple parsing goals
- public ReferenceContext referenceContext;
- public int currentToken;
- private int synchronizedBlockSourceStart;
+public class Parser implements ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
+ protected static final int THIS_CALL = ExplicitConstructorCall.This;
+ protected static final int SUPER_CALL = ExplicitConstructorCall.Super;
- //error recovery management
- protected int lastCheckPoint;
- protected RecoveredElement currentElement;
- public static boolean VERBOSE_RECOVERY = false;
- protected boolean restartRecovery;
- protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
- protected boolean hasError;
- protected boolean hasReportedError;
- public boolean reportSyntaxErrorIsRequired = true;
- public boolean reportOnlyOneSyntaxError = false;
- protected int recoveredStaticInitializerStart;
- protected int lastIgnoredToken, nextIgnoredToken;
- protected int lastErrorEndPosition;
- protected boolean ignoreNextOpeningBrace;
+ public static char asb[] = null;
+ public static char asr[] = null;
+ //ast stack
+ protected final static int AstStackIncrement = 100;
+ public static char base_action[] = null;
+ public static final int BracketKinds = 3;
+
+ public static short check_table[] = null;
+ public static final int CurlyBracket = 2;
+ // TODO remove once testing is done
+ private static final boolean DEBUG = false;
+ private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
+ private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
+ //expression stack
+ protected final static int ExpressionStackIncrement = 100;
+
+ protected final static int GenericsStackIncrement = 10;
+
+ private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
+ public static char in_symb[] = null;
+ private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
+ public static char lhs[] = null;
+
+ public static String name[] = null;
+ public static char nasb[] = null;
+ public static char nasr[] = null;
+ public static char non_terminal_index[] = null;
+ private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
+ private final static String READABLE_NAMES_FILE_NAME =
+ "org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+ public static String readableName[] = null;
+
+ public static byte rhs[] = null;
+
+ public static long rules_compliance[] = null;
+
+ public static final int RoundBracket = 0;
+
+ public static byte scope_la[] = null;
+ public static char scope_lhs[] = null;
+
+ public static char scope_prefix[] = null;
+ public static char scope_rhs[] = null;
+ public static char scope_state[] = null;
+
+ public static char scope_state_set[] = null;
+ public static char scope_suffix[] = null;
+ public static final int SquareBracket = 1;
//internal data for the automat
protected final static int StackIncrement = 255;
- protected int stateStackTop;
- protected int[] stack = new int[StackIncrement];
- //scanner token
- public Scanner scanner;
- //ast stack
- final static int AstStackIncrement = 100;
- protected int astPtr;
- protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
+
+ public static char term_action[] = null;
+ public static byte term_check[] = null;
+
+ public static char terminal_index[] = null;
+
+ private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
+ public static boolean VERBOSE_RECOVERY = false;
+
+
+
protected int astLengthPtr;
protected int[] astLengthStack;
+ protected int astPtr;
+ protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
- ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
- //expression stack
- final static int ExpressionStackIncrement = 100;
- protected int expressionPtr;
- protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+ protected RecoveredElement currentElement;
+ public int currentToken;
+ protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
+ protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
+ protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
+ protected int endStatementPosition;
protected int expressionLengthPtr;
protected int[] expressionLengthStack;
- Expression [] noExpressions = new Expression[ExpressionStackIncrement];
+ protected int expressionPtr;
+ protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+ public int firstToken ; // handle for multiple parsing goals
+
+ // generics management
+ protected int genericsIdentifiersLengthPtr;
+ protected int[] genericsIdentifiersLengthStack = new int[GenericsStackIncrement];
+ protected int genericsLengthPtr;
+ protected int[] genericsLengthStack = new int[GenericsStackIncrement];
+ protected int genericsPtr;
+ protected ASTNode[] genericsStack = new ASTNode[GenericsStackIncrement];
+
+ protected boolean hasError;
+ protected boolean hasReportedError;
+
//identifiers stacks
- protected int identifierPtr;
- protected char[][] identifierStack;
protected int identifierLengthPtr;
protected int[] identifierLengthStack;
protected long[] identifierPositionStack;
+ protected int identifierPtr;
+ protected char[][] identifierStack;
+
+ protected boolean ignoreNextOpeningBrace;
//positions , dimensions , .... (int stacks)
protected int intPtr;
protected int[] intStack;
- protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
- protected int endStatementPosition;
+ public int lastAct ; //handle for multiple parsing goals
+
+ //error recovery management
+ protected int lastCheckPoint;
+ protected int lastErrorEndPosition;
+ protected int lastErrorEndPositionBeforeRecovery = -1;
+ protected int lastIgnoredToken, nextIgnoredToken;
+ protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
+ protected int listTypeParameterLength; // for recovering some incomplete list (type parameters)
protected int lParenPos,rParenPos; //accurate only when used !
- protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
- //modifiers dimensions nestedType etc.......
- protected boolean optimizeStringLiterals =true;
protected int modifiers;
protected int modifiersSourceStart;
- protected int nestedType, dimensions;
protected int[] nestedMethod; //the ptr is nestedType
- protected int[] realBlockStack;
+ protected int nestedType, dimensions;
+ ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
+ Expression [] noExpressions = new Expression[ExpressionStackIncrement];
+ //modifiers dimensions nestedType etc.......
+ protected boolean optimizeStringLiterals =true;
+ protected CompilerOptions options;
+ protected ProblemReporter problemReporter;
+ protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
protected int realBlockPtr;
- protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
- protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
+ protected int[] realBlockStack;
+ protected int recoveredStaticInitializerStart;
+ public ReferenceContext referenceContext;
+ public boolean reportOnlyOneSyntaxError = false;
+ public boolean reportSyntaxErrorIsRequired = true;
+ protected boolean restartRecovery;
+ //scanner token
+ public Scanner scanner;
+ protected int[] stack = new int[StackIncrement];
+ protected int stateStackTop;
+ protected int synchronizedBlockSourceStart;
protected int[] variablesCounter;
// javadoc
- public JavadocParser javadocParser;
public Javadoc javadoc;
-
- public static byte rhs[] = null;
- public static char asb[] = null;
- public static char asr[] = null;
- public static char nasb[] = null;
- public static char nasr[] = null;
-
- public static char terminal_index[] = null;
- public static char non_terminal_index[] = null;
-
- public static char term_action[] = null;
- public static byte term_check[] = null;
-
- private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
- private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
- private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
- private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
-
- public static String name[] = null;
- public static String readableName[] = null;
-
- public static short check_table[] = null;
- public static char lhs[] = null;
- public static char base_action[] = lhs;
-
- public static char scope_prefix[] = null;
- public static char scope_suffix[] = null;
- public static char scope_lhs[] = null;
-
- public static byte scope_la[] = null;
-
- public static char scope_state_set[] = null;
- public static char scope_rhs[] = null;
- public static char scope_state[] = null;
- public static char in_symb[] = null;
-
- private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
- private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
- private final static String READABLE_NAMES =
- "org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
+ public JavadocParser javadocParser;
+ // used for recovery
+ protected int lastJavadocEnd;
static {
try{
@@ -157,136 +191,21 @@ public class Parser implements BindingIds, ParserBasicInformation, TerminalToken
throw new ExceptionInInitializerError(ex.getMessage());
}
}
-
- public static final int RoundBracket = 0;
- public static final int SquareBracket = 1;
- public static final int CurlyBracket = 2;
- public static final int BracketKinds = 3;
-
-public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
-
- this.problemReporter = problemReporter;
- this.options = problemReporter.options;
- this.optimizeStringLiterals = optimizeStringLiterals;
- this.initializeScanner();
- this.astLengthStack = new int[50];
- this.expressionLengthStack = new int[30];
- this.intStack = new int[50];
- this.identifierStack = new char[30][];
- this.identifierLengthStack = new int[30];
- this.nestedMethod = new int[30];
- this.realBlockStack = new int[30];
- this.identifierPositionStack = new long[30];
- this.variablesCounter = new int[30];
-
- // javadoc support
- this.javadocParser = new JavadocParser(this);
-}
-/**
- *
- * INTERNAL USE-ONLY
- */
-protected void adjustInterfaceModifiers() {
- this.intStack[this.intPtr - 1] |= AccInterface;
-}
-public final void arrayInitializer(int length) {
- //length is the size of the array Initializer
- //expressionPtr points on the last elt of the arrayInitializer,
- // in other words, it has not been decremented yet.
-
- ArrayInitializer ai = new ArrayInitializer();
- if (length != 0) {
- this.expressionPtr -= length;
- System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
- }
- pushOnExpressionStack(ai);
- //positionning
- ai.sourceEnd = this.endStatementPosition;
- int searchPosition = length == 0 ? this.endPosition + 1 : ai.expressions[0].sourceStart;
- try {
- //does not work with comments(that contain '{') nor '{' describes as a unicode....
- while (this.scanner.source[--searchPosition] != '{'){/*empty*/}
- } catch (IndexOutOfBoundsException ex) {
- //should never occur (except for strange cases like whose describe above)
- searchPosition = (length == 0 ? this.endPosition : ai.expressions[0].sourceStart) - 1;
- }
- ai.sourceStart = searchPosition;
-}
public static int asi(int state) {
return asb[original_state(state)];
}
-protected void blockReal() {
- // See consumeLocalVariableDeclarationStatement in case of change: duplicated code
- // increment the amount of declared variables for this block
- this.realBlockStack[this.realBlockPtr]++;
+public final static short base_check(int i) {
+ return check_table[i - (NUM_RULES + 1)];
}
-private final static void buildFileOfByteFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
- //transform the String tokens into chars before dumping then into file
-
- int i = 0;
- //read upto the tag
- while (!tokens[i++].equals(tag)){/*empty*/}
- //read upto the }
-
- byte[] bytes = new byte[tokens.length]; //can't be bigger
- int ic = 0;
- String token;
- while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
- int c = Integer.parseInt(token);
- bytes[ic++] = (byte) c;
+private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
+ BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
+ for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
+ writer.write(String.valueOf(iterator.next()));
}
-
- //resize
- System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
-
- buildFileForTable(filename, bytes);
-}
-private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
- //transform the String tokens into chars before dumping then into file
-
- int i = 0;
- //read upto the tag
- while (!tokens[i++].equals(tag)){/*empty*/}
- //read upto the }
-
- char[] chars = new char[tokens.length]; //can't be bigger
- int ic = 0;
- String token;
- while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
- int c = Integer.parseInt(token);
- chars[ic++] = (char) c;
- }
-
- //resize
- System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
-
- buildFileForTable(filename, chars);
- return chars;
-}
-private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) throws java.io.IOException {
-
- //transform the String tokens into chars before dumping then into file
-
- int i = 0;
- //read upto the tag
- while (!tokens[i++].equals(tag)){/*empty*/}
- //read upto the }
-
- char[] chars = new char[tokens.length]; //can't be bigger
- int ic = 0;
- String token;
- while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
- int c = Integer.parseInt(token);
- chars[ic++] = (char) (c + 32768);
- }
-
- //resize
- System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
-
- buildFileForTable(filename, chars);
+ writer.flush();
+ writer.close();
+ System.out.println(filename + " creation complete"); //$NON-NLS-1$
}
private final static String[] buildFileForName(String filename, String contents) throws java.io.IOException {
String[] result = new String[contents.length()];
@@ -351,16 +270,18 @@ private static void buildFileForReadableName(
boolean[] alreadyAdded = new boolean[newName.length];
- for (int i = 0; i < tokens.length; i = i + 2) {
- int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i])]];
- StringBuffer buffer = new StringBuffer();
- if(!alreadyAdded[index]) {
- alreadyAdded[index] = true;
- buffer.append(newName[index]);
- buffer.append('=');
- buffer.append(tokens[i+1].trim());
- buffer.append('\n');
- entries.add(String.valueOf(buffer));
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if("1".equals(tokens[i])) { //$NON-NLS-1$
+ int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i + 1])]];
+ StringBuffer buffer = new StringBuffer();
+ if(!alreadyAdded[index]) {
+ alreadyAdded[index] = true;
+ buffer.append(newName[index]);
+ buffer.append('=');
+ buffer.append(tokens[i+2].trim());
+ buffer.append('\n');
+ entries.add(String.valueOf(buffer));
+ }
}
}
int i = 1;
@@ -374,13 +295,44 @@ private static void buildFileForReadableName(
Collections.sort(entries);
buildFile(file, entries);
}
-private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
- BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
- for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
- writer.write(String.valueOf(iterator.next()));
+private static void buildFileForCompliance(
+ String file,
+ int length,
+ String[] tokens) throws java.io.IOException {
+
+ byte[] result = new byte[length * 8];
+
+ for (int i = 0; i < tokens.length; i = i + 3) {
+ if("2".equals(tokens[i])) { //$NON-NLS-1$
+ int index = Integer.parseInt(tokens[i + 1]);
+ String token = tokens[i + 2].trim();
+ long compliance = 0;
+ if("1.4".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK1_4;
+ } else if("1.5".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK1_5;
+ } else if("recovery".equals(token)) { //$NON-NLS-1$
+ compliance = ClassFileConstants.JDK_DEFERRED;
+ }
+
+ int j = index * 8;
+ result[j] = (byte)(compliance >>> 56);
+ result[j + 1] = (byte)(compliance >>> 48);
+ result[j + 2] = (byte)(compliance >>> 40);
+ result[j + 3] = (byte)(compliance >>> 32);
+ result[j + 4] = (byte)(compliance >>> 24);
+ result[j + 5] = (byte)(compliance >>> 16);
+ result[j + 6] = (byte)(compliance >>> 8);
+ result[j + 7] = (byte)(compliance);
+ }
+ }
+
+ buildFileForTable(file, result); //$NON-NLS-1$
}
- writer.flush();
- writer.close();
+private final static void buildFileForTable(String filename, byte[] bytes) throws java.io.IOException {
+ java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
+ stream.write(bytes);
+ stream.close();
System.out.println(filename + " creation complete"); //$NON-NLS-1$
}
private final static void buildFileForTable(String filename, char[] chars) throws java.io.IOException {
@@ -396,11 +348,73 @@ private final static void buildFileForTable(String filename, char[] chars) throw
stream.close();
System.out.println(filename + " creation complete"); //$NON-NLS-1$
}
-private final static void buildFileForTable(String filename, byte[] bytes) throws java.io.IOException {
- java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
- stream.write(bytes);
- stream.close();
- System.out.println(filename + " creation complete"); //$NON-NLS-1$
+private final static byte[] buildFileOfByteFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)){/*empty*/}
+ //read upto the }
+
+ byte[] bytes = new byte[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ bytes[ic++] = (byte) c;
+ }
+
+ //resize
+ System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
+
+ buildFileForTable(filename, bytes);
+ return bytes;
+}
+private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)){/*empty*/}
+ //read upto the }
+
+ char[] chars = new char[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ chars[ic++] = (char) c;
+ }
+
+ //resize
+ System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+ buildFileForTable(filename, chars);
+ return chars;
+}
+private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)){/*empty*/}
+ //read upto the }
+
+ char[] chars = new char[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ chars[ic++] = (char) (c + 32768);
+ }
+
+ //resize
+ System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+ buildFileForTable(filename, chars);
}
public final static void buildFilesFromLPG(String dataFilename, String dataFilename2) throws java.io.IOException {
@@ -410,7 +424,6 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
//lhs check_table asb asr symbol_index
//[org.eclipse.jdt.internal.compiler.parser.Parser.buildFilesFromLPG("d:/leapfrog/grammar/javadcl.java")]
-
char[] contents = new char[] {};
try {
contents = Util.getFileCharContent(new File(dataFilename), null);
@@ -421,12 +434,12 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
java.util.StringTokenizer st =
new java.util.StringTokenizer(new String(contents), " \t\n\r[]={,;"); //$NON-NLS-1$
String[] tokens = new String[st.countTokens()];
- int i = 0;
+ int j = 0;
while (st.hasMoreTokens()) {
- tokens[i++] = st.nextToken();
+ tokens[j++] = st.nextToken();
}
final String prefix = FILEPREFIX;
- i = 0;
+ int i = 0;
char[] newLhs = buildFileOfIntFor(prefix + (++i) + ".rsc", "lhs", tokens); //$NON-NLS-1$ //$NON-NLS-2$
buildFileOfShortFor(prefix + (++i) + ".rsc", "check_table", tokens); //$NON-NLS-2$ //$NON-NLS-1$
@@ -446,7 +459,7 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
- buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+ byte[] newRhs = buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
buildFileOfByteFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
buildFileOfByteFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
@@ -459,78 +472,319 @@ public final static void buildFilesFromLPG(String dataFilename, String dataFilen
System.out.println(Util.bind("parser.incorrectPath")); //$NON-NLS-1$
return;
}
- st = new java.util.StringTokenizer(new String(contents), "\t\n\r="); //$NON-NLS-1$
+ st = new java.util.StringTokenizer(new String(contents), "\t\n\r=#"); //$NON-NLS-1$
tokens = new String[st.countTokens()];
- i = 0;
+ j = 0;
while (st.hasMoreTokens()) {
- tokens[i++] = st.nextToken();
+ tokens[j++] = st.nextToken();
}
+
+ buildFileForCompliance(prefix + (++i) + ".rsc", newRhs.length, tokens);//$NON-NLS-1$
buildFileForReadableName(READABLE_NAMES_FILE+".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
System.out.println(Util.bind("parser.moveFiles")); //$NON-NLS-1$
}
-/*
- * Build initial recovery state.
- * Recovery state is inferred from the current state of the parser (reduced node stack).
- */
-public RecoveredElement buildInitialRecoveryState(){
+public static int in_symbol(int state) {
+ return in_symb[original_state(state)];
+}
+public final static void initTables() throws java.io.IOException {
- /* initialize recovery by retrieving available reduced nodes
- * also rebuild bracket balance
- */
- this.lastCheckPoint = 0;
+ final String prefix = FILEPREFIX;
+ int i = 0;
+ lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ check_table = new short[chars.length];
+ for (int c = chars.length; c-- > 0;) {
+ check_table[c] = (short) (chars[c] - 32768);
+ }
+ asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ rules_compliance = readLongTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+
+ readableName = readReadableNameTable(READABLE_NAMES_FILE_NAME);
+
+ base_action = lhs;
+}
+public static int nasi(int state) {
+ return nasb[original_state(state)];
+}
+public static int ntAction(int state, int sym) {
+ return base_action[state + sym];
+}
+protected static int original_state(int state) {
+ return -base_check(state);
+}
+protected static byte[] readByteTable(String filename) throws java.io.IOException {
- RecoveredElement element = null;
- if (this.referenceContext instanceof CompilationUnitDeclaration){
- element = new RecoveredUnit(this.compilationUnit, 0, this);
-
- /* ignore current stack state, since restarting from the beginnning
- since could not trust simple brace count */
- if (true){ // experimenting restart recovery from scratch
- this.compilationUnit.currentPackage = null;
- this.compilationUnit.imports = null;
- this.compilationUnit.types = null;
- this.currentToken = 0;
- this.listLength = 0;
- this.endPosition = 0;
- this.endStatementPosition = 0;
- return element;
- }
- if (this.compilationUnit.currentPackage != null){
- this.lastCheckPoint = this.compilationUnit.currentPackage.declarationSourceEnd+1;
- }
- if (this.compilationUnit.imports != null){
- this.lastCheckPoint = this.compilationUnit.imports[this.compilationUnit.imports.length -1].declarationSourceEnd+1;
- }
- } else {
- if (this.referenceContext instanceof AbstractMethodDeclaration){
- element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
- this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
- } else {
- /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
- if (this.referenceContext instanceof TypeDeclaration){
- TypeDeclaration type = (TypeDeclaration) this.referenceContext;
- for (int i = 0; i < type.fields.length; i++){
- FieldDeclaration field = type.fields[i];
- if (field != null
- && !field.isField()
- && field.declarationSourceStart <= this.scanner.initialPosition
- && this.scanner.initialPosition <= field.declarationSourceEnd
- && this.scanner.eofPosition <= field.declarationSourceEnd+1){
- element = new RecoveredInitializer(field, null, 1, this);
- this.lastCheckPoint = field.declarationSourceStart;
- break;
- }
- }
- }
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
}
}
-
- if (element == null) return element;
+ return bytes;
+}
- for(int i = 0; i <= this.astPtr; i++){
- ASTNode node = this.astStack[i];
- if (node instanceof AbstractMethodDeclaration){
+protected static String[] readNameTable(String filename) throws java.io.IOException {
+ char[] contents = readTable(filename);
+ char[][] nameAsChar = CharOperation.splitOn('\n', contents);
+
+ String[] result = new String[nameAsChar.length + 1];
+ result[0] = null;
+ for (int i = 0; i < nameAsChar.length; i++) {
+ result[i + 1] = new String(nameAsChar[i]);
+ }
+
+ return result;
+}
+protected static String[] readReadableNameTable(String filename) {
+ String[] result = new String[name.length];
+
+ ResourceBundle bundle;
+ try {
+ bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
+ } catch(MissingResourceException e) {
+ System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+ throw e;
+ }
+ for (int i = 0; i < NT_OFFSET + 1; i++) {
+ result[i] = name[i];
+ }
+ for (int i = NT_OFFSET; i < name.length; i++) {
+ try {
+ String n = bundle.getString(name[i]);
+ if(n != null && n.length() > 0) {
+ result[i] = n;
+ } else {
+ result[i] = name[i];
+ }
+ } catch(MissingResourceException e) {
+ result[i] = name[i];
+ }
+ }
+ return result;
+}
+protected static char[] readTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ //minimal integrity check (even size expected)
+ int length = bytes.length;
+ if (length % 2 != 0)
+ throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
+
+ // convert bytes into chars
+ char[] chars = new char[length / 2];
+ int i = 0;
+ int charIndex = 0;
+
+ while (true) {
+ chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
+ if (i == length)
+ break;
+ }
+ return chars;
+}
+protected static long[] readLongTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = Parser.class.getResourceAsStream(filename);
+ if (stream == null) {
+ throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+ }
+ byte[] bytes = null;
+ try {
+ stream = new BufferedInputStream(stream);
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ //minimal integrity check (even size expected)
+ int length = bytes.length;
+ if (length % 8 != 0)
+ throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
+
+ // convert bytes into longs
+ long[] longs = new long[length / 8];
+ int i = 0;
+ int longIndex = 0;
+
+ while (true) {
+ longs[longIndex++] =
+ (((long) (bytes[i++] & 0xFF)) << 56)
+ + (((long) (bytes[i++] & 0xFF)) << 48)
+ + (((long) (bytes[i++] & 0xFF)) << 40)
+ + (((long) (bytes[i++] & 0xFF)) << 32)
+ + (((long) (bytes[i++] & 0xFF)) << 24)
+ + (((long) (bytes[i++] & 0xFF)) << 16)
+ + (((long) (bytes[i++] & 0xFF)) << 8)
+ + (bytes[i++] & 0xFF);
+
+ if (i == length)
+ break;
+ }
+ return longs;
+}
+public static int tAction(int state, int sym) {
+ return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
+}
+
+public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
+
+ this.problemReporter = problemReporter;
+ this.options = problemReporter.options;
+ this.optimizeStringLiterals = optimizeStringLiterals;
+ this.initializeScanner();
+ this.astLengthStack = new int[50];
+ this.expressionLengthStack = new int[30];
+ this.intStack = new int[50];
+ this.identifierStack = new char[30][];
+ this.identifierLengthStack = new int[30];
+ this.nestedMethod = new int[30];
+ this.realBlockStack = new int[30];
+ this.identifierPositionStack = new long[30];
+ this.variablesCounter = new int[30];
+
+ // javadoc support
+ this.javadocParser = new JavadocParser(this);
+}
+public void arrayInitializer(int length) {
+ //length is the size of the array Initializer
+ //expressionPtr points on the last elt of the arrayInitializer,
+ // in other words, it has not been decremented yet.
+
+ ArrayInitializer ai = new ArrayInitializer();
+ if (length != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(this.expressionStack, this.expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
+ }
+ pushOnExpressionStack(ai);
+ //positionning
+ ai.sourceEnd = this.endStatementPosition;
+ ai.sourceStart = this.intStack[this.intPtr--];
+}
+protected void blockReal() {
+ // See consumeLocalVariableDeclarationStatement in case of change: duplicated code
+ // increment the amount of declared variables for this block
+ this.realBlockStack[this.realBlockPtr]++;
+}
+/*
+ * Build initial recovery state.
+ * Recovery state is inferred from the current state of the parser (reduced node stack).
+ */
+public RecoveredElement buildInitialRecoveryState(){
+
+ /* initialize recovery by retrieving available reduced nodes
+ * also rebuild bracket balance
+ */
+ this.lastCheckPoint = 0;
+ this.lastErrorEndPositionBeforeRecovery = this.scanner.currentPosition;
+
+ RecoveredElement element = null;
+ if (this.referenceContext instanceof CompilationUnitDeclaration){
+ element = new RecoveredUnit(this.compilationUnit, 0, this);
+
+ /* ignore current stack state, since restarting from the beginnning
+ since could not trust simple brace count */
+ if (true){ // experimenting restart recovery from scratch
+ this.compilationUnit.currentPackage = null;
+ this.compilationUnit.imports = null;
+ this.compilationUnit.types = null;
+ this.currentToken = 0;
+ this.listLength = 0;
+ this.listTypeParameterLength = 0;
+ this.endPosition = 0;
+ this.endStatementPosition = 0;
+ return element;
+ }
+ if (this.compilationUnit.currentPackage != null){
+ this.lastCheckPoint = this.compilationUnit.currentPackage.declarationSourceEnd+1;
+ }
+ if (this.compilationUnit.imports != null){
+ this.lastCheckPoint = this.compilationUnit.imports[this.compilationUnit.imports.length -1].declarationSourceEnd+1;
+ }
+ } else {
+ if (this.referenceContext instanceof AbstractMethodDeclaration){
+ element = new RecoveredMethod((AbstractMethodDeclaration) this.referenceContext, null, 0, this);
+ this.lastCheckPoint = ((AbstractMethodDeclaration) this.referenceContext).bodyStart;
+ } else {
+ /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
+ if (this.referenceContext instanceof TypeDeclaration){
+ TypeDeclaration type = (TypeDeclaration) this.referenceContext;
+ for (int i = 0; i < type.fields.length; i++){
+ FieldDeclaration field = type.fields[i];
+ if (field != null
+ && field.getKind() == AbstractVariableDeclaration.INITIALIZER
+ && field.declarationSourceStart <= this.scanner.initialPosition
+ && this.scanner.initialPosition <= field.declarationSourceEnd
+ && this.scanner.eofPosition <= field.declarationSourceEnd+1){
+ element = new RecoveredInitializer(field, null, 1, this);
+ this.lastCheckPoint = field.declarationSourceStart;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (element == null) return element;
+
+ for(int i = 0; i <= this.astPtr; i++){
+ ASTNode node = this.astStack[i];
+ if (node instanceof AbstractMethodDeclaration){
AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
if (method.declarationSourceEnd == 0){
element = element.add(method, 0);
@@ -586,16 +840,14 @@ public RecoveredElement buildInitialRecoveryState(){
}
return element;
}
-public final static short base_check(int i) {
- return check_table[i - (NUM_RULES + 1)];
-}
-public final void checkAndSetModifiers(int flag){
+
+protected void checkAndSetModifiers(int flag){
/*modify the current modifiers buffer.
When the startPosition of the modifiers is 0
it means that the modifier being parsed is the first
of a list of several modifiers. The startPosition
is zeroed when a copy of modifiers-buffer is push
- onto the astStack. */
+ onto the this.astStack. */
if ((this.modifiers & flag) != 0){ // duplicate modifier
this.modifiers |= AccAlternateModifierProblem;
@@ -606,8 +858,9 @@ public final void checkAndSetModifiers(int flag){
}
public void checkComment() {
- if (this.currentElement != null && this.scanner.commentPtr >= 0) {
- flushCommentsDefinedPriorTo(this.endStatementPosition); // discard obsolete comments during recovery
+ // discard obsolete comments while inside methods or fields initializer (see bug 74369)
+ if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
+ flushCommentsDefinedPriorTo(this.endStatementPosition);
}
int lastComment = this.scanner.commentPtr;
@@ -623,12 +876,14 @@ public void checkComment() {
// check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)
while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
if (lastComment >= 0 && this.javadocParser != null) {
- if (this.javadocParser.checkDeprecation(
- this.scanner.commentStarts[lastComment],
- this.scanner.commentStops[lastComment] - 1)) { //stop is one over,
+ int commentEnd = this.scanner.commentStops[lastComment] - 1; //stop is one over,
+ // do not report problem before last parsed comment while recovering code...
+ this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
+ if (this.javadocParser.checkDeprecation(this.scanner.commentStarts[lastComment], commentEnd)) {
checkAndSetModifiers(AccDeprecated);
}
- this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
+ this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
+ if (currentElement == null) this.lastJavadocEnd = commentEnd;
}
}
}
@@ -656,25 +911,7 @@ protected void checkNonNLSAfterBodyEnd(int declarationEnd){
}
}
}
-protected char getNextCharacter(char[] comment, int[] index) {
- char nextCharacter = comment[index[0]++];
- switch(nextCharacter) {
- case '\\' :
- int c1, c2, c3, c4;
- index[0]++;
- while (comment[index[0]] == 'u') index[0]++;
- if (!(((c1 = Character.getNumericValue(comment[index[0]++])) > 15
- || c1 < 0)
- || ((c2 = Character.getNumericValue(comment[index[0]++])) > 15 || c2 < 0)
- || ((c3 = Character.getNumericValue(comment[index[0]++])) > 15 || c3 < 0)
- || ((c4 = Character.getNumericValue(comment[index[0]++])) > 15 || c4 < 0))) {
- nextCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
- }
- break;
- }
- return nextCharacter;
-}
-protected void classInstanceCreation(boolean alwaysQualified) {
+protected void classInstanceCreation(boolean hasClassBody) {
// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
// ClassBodyopt produces a null item on the astStak if it produces NO class body
@@ -686,7 +923,7 @@ protected void classInstanceCreation(boolean alwaysQualified) {
&& (this.astStack[this.astPtr] == null)) {
//NO ClassBody
this.astPtr--;
- if (alwaysQualified) {
+ if (hasClassBody) {
alloc = new QualifiedAllocationExpression();
} else {
alloc = new AllocationExpression();
@@ -703,6 +940,7 @@ protected void classInstanceCreation(boolean alwaysQualified) {
length);
}
alloc.type = getTypeReference(0);
+
//the default constructor with the correct number of argument
//will be created and added by the TC (see createsInternalConstructorWithBinding)
alloc.sourceStart = this.intStack[this.intPtr--];
@@ -720,30 +958,46 @@ protected void classInstanceCreation(boolean alwaysQualified) {
}
this.astPtr--;
this.astLengthPtr--;
-
+
// mark initializers with local type mark if needed
markInitializersWithLocalType(anonymousTypeDeclaration);
}
}
-protected final void concatExpressionLists() {
+protected void concatExpressionLists() {
this.expressionLengthStack[--this.expressionLengthPtr]++;
}
-private final void concatNodeLists() {
+protected void concatGenericsLists() {
+ this.genericsLengthStack[this.genericsLengthPtr - 1] += this.genericsLengthStack[this.genericsLengthPtr--];
+}
+protected void concatNodeLists() {
/*
- * This is a case where you have two sublists into the astStack that you want
- * to merge in one list. There is no action required on the astStack. The only
+ * This is a case where you have two sublists into the this.astStack that you want
+ * to merge in one list. There is no action required on the this.astStack. The only
* thing you need to do is merge the two lengths specified on the astStackLength.
* The top two length are for example:
* ... p n
* and you want to result in a list like:
* ... n+p
* This means that the p could be equals to 0 in case there is no astNode pushed
- * on the astStack.
+ * on the this.astStack.
* Look at the InterfaceMemberDeclarations for an example.
*/
this.astLengthStack[this.astLengthPtr - 1] += this.astLengthStack[this.astLengthPtr--];
}
+protected void consumeAdditionalBound() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
+}
+protected void consumeAdditionalBound1() {
+ // nothing to be done.
+ // The reference type1 is consumed by consumeReferenceType1 method.
+}
+protected void consumeAdditionalBoundList() {
+ concatGenericsLists();
+}
+protected void consumeAdditionalBoundList1() {
+ concatGenericsLists();
+}
protected void consumeAllocationHeader() {
// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
@@ -764,7 +1018,6 @@ protected void consumeAllocationHeader() {
alloc.type = getTypeReference(0);
alloc.sourceStart = anonymousType.sourceStart;
alloc.sourceEnd = anonymousType.sourceEnd ;
- anonymousType.allocation = alloc;
this.lastCheckPoint = anonymousType.bodyStart = this.scanner.currentPosition;
this.currentElement = this.currentElement.add(anonymousType, 0);
this.lastIgnoredToken = -1;
@@ -774,16 +1027,140 @@ protected void consumeAllocationHeader() {
this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
this.restartRecovery = true; // request to restart from here on
}
-protected void consumeArgumentList() {
- // ArgumentList ::= ArgumentList ',' Expression
- concatExpressionLists();
+protected void consumeAnnotationAsModifier() {
+ // nothing to do
}
-protected void consumeArrayAccess(boolean unspecifiedReference) {
- // ArrayAccess ::= Name '[' Expression ']' ==> true
- // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
-
+protected void consumeAnnotationName() {
+ // nothing to do
+}
+protected void consumeAnnotationTypeDeclaration() {
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ //there are length declarations
+ //dispatch according to the type of the declarations
+ dispatchDeclarationInto(length);
+ }
- //optimize push/pop
+ TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+
+ // mark initializers with local type mark if needed
+ markInitializersWithLocalType(typeDecl);
+
+ //convert constructor that do not have the type's name into methods
+ typeDecl.checkConstructors(this);
+
+ //always add (will be remove at code gen time if empty)
+ if (this.scanner.containsAssertKeyword) {
+ typeDecl.bits |= ASTNode.AddAssertionMASK;
+ }
+ typeDecl.addClinit();
+ typeDecl.bodyEnd = this.endStatementPosition;
+ if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+ typeDecl.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+ }
+ typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeAnnotationTypeDeclarationHeader() {
+ if (this.currentElement != null) {
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+}
+protected void consumeAnnotationTypeDeclarationHeaderName() {
+ // consumeAnnotationTypeDeclarationHeader ::= Modifiers '@' PushModifiers interface Identifier
+ // consumeAnnotationTypeDeclarationHeader ::= '@' PushModifiers interface Identifier
+ TypeDeclaration annotationTypeDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
+ if (this.nestedMethod[this.nestedType] == 0) {
+ if (this.nestedType != 0) {
+ annotationTypeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ annotationTypeDeclaration.bits |= ASTNode.IsLocalTypeMASK;
+ markEnclosingMemberWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = this.identifierPositionStack[this.identifierPtr];
+ annotationTypeDeclaration.sourceEnd = (int) pos;
+ annotationTypeDeclaration.sourceStart = (int) (pos >>> 32);
+ annotationTypeDeclaration.name = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'interface' push two int positions: the beginning of the class token and its end.
+ // we want to keep the beginning position but get rid of the end position
+ // it is only used for the ClassLiteralAccess positions.
+ this.intPtr--; // remove the start position of the interface token
+ this.intPtr--; // remove the end position of the interface token
+
+ annotationTypeDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
+ annotationTypeDeclaration.modifiers = this.intStack[this.intPtr--] | AccAnnotation | AccInterface;
+ if (annotationTypeDeclaration.modifiersSourceStart >= 0) {
+ annotationTypeDeclaration.declarationSourceStart = annotationTypeDeclaration.modifiersSourceStart;
+ this.intPtr--; // remove the position of the '@' token as we have modifiers
+ } else {
+ int atPosition = this.intStack[this.intPtr--];
+ // remove the position of the '@' token as we don't have modifiers
+ annotationTypeDeclaration.declarationSourceStart = atPosition;
+ }
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ annotationTypeDeclaration.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+ annotationTypeDeclaration.bodyStart = annotationTypeDeclaration.sourceEnd + 1;
+
+ // javadoc
+ annotationTypeDeclaration.javadoc = this.javadoc;
+ this.javadoc = null;
+ pushOnAstStack(annotationTypeDeclaration);
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfAnnotationDeclarations(annotationTypeDeclaration);
+ }
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = annotationTypeDeclaration.bodyStart;
+ this.currentElement = this.currentElement.add(annotationTypeDeclaration, 0);
+ this.lastIgnoredToken = -1;
+ }
+}
+protected void consumeAnnotationTypeMemberDeclaration() {
+ // AnnotationTypeMemberDeclaration ::= AnnotationTypeMemberDeclarationHeader AnnotationTypeMemberHeaderExtendedDims DefaultValueopt ';'
+ AnnotationMethodDeclaration annotationTypeMemberDeclaration = (AnnotationMethodDeclaration) this.astStack[this.astPtr];
+ annotationTypeMemberDeclaration.modifiers |= AccSemicolonBody;
+ // store the this.endPosition (position just before the '}') in case there is
+ // a trailing comment behind the end of the method
+ int declarationEndPosition = flushCommentsDefinedPriorTo(this.endStatementPosition);
+ annotationTypeMemberDeclaration.bodyStart = this.endStatementPosition;
+ annotationTypeMemberDeclaration.bodyEnd = declarationEndPosition;
+ annotationTypeMemberDeclaration.declarationSourceEnd = declarationEndPosition;
+}
+protected void consumeAnnotationTypeMemberDeclarations() {
+ // AnnotationTypeMemberDeclarations ::= AnnotationTypeMemberDeclarations AnnotationTypeMemberDeclaration
+ concatNodeLists();
+}
+protected void consumeArgumentList() {
+ // ArgumentList ::= ArgumentList ',' Expression
+ concatExpressionLists();
+}
+protected void consumeArguments() {
+ // Arguments ::= '(' ArgumentListopt ')'
+ // nothing to do, the expression stack is already updated
+}
+protected void consumeArrayAccess(boolean unspecifiedReference) {
+ // ArrayAccess ::= Name '[' Expression ']' ==> true
+ // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
+
+
+ //optimize push/pop
Expression exp;
if (unspecifiedReference) {
exp =
@@ -802,12 +1179,15 @@ protected void consumeArrayAccess(boolean unspecifiedReference) {
}
exp.sourceEnd = this.endPosition;
}
-protected void consumeArrayCreationExpressionWithoutInitializer() {
- // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
- // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
+protected void consumeArrayCreationExpressionWithInitializer() {
+ // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
+ // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
int length;
ArrayAllocationExpression aae = new ArrayAllocationExpression();
+ this.expressionLengthPtr -- ;
+ aae.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
+
aae.type = getTypeReference(0);
length = (this.expressionLengthStack[this.expressionLengthPtr--]);
this.expressionPtr -= length ;
@@ -825,19 +1205,12 @@ protected void consumeArrayCreationExpressionWithoutInitializer() {
}
pushOnExpressionStack(aae);
}
-
-protected void consumeArrayCreationHeader() {
- // nothing to do
-}
-protected void consumeArrayCreationExpressionWithInitializer() {
- // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
- // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
+protected void consumeArrayCreationExpressionWithoutInitializer() {
+ // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
+ // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
int length;
ArrayAllocationExpression aae = new ArrayAllocationExpression();
- this.expressionLengthPtr -- ;
- aae.initializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
-
aae.type = getTypeReference(0);
length = (this.expressionLengthStack[this.expressionLengthPtr--]);
this.expressionPtr -= length ;
@@ -855,19 +1228,23 @@ protected void consumeArrayCreationExpressionWithInitializer() {
}
pushOnExpressionStack(aae);
}
+protected void consumeArrayCreationHeader() {
+ // nothing to do
+}
protected void consumeArrayInitializer() {
// ArrayInitializer ::= '{' VariableInitializers '}'
// ArrayInitializer ::= '{' VariableInitializers , '}'
arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
}
-
+protected void consumeArrayTypeWithTypeArgumentsName() {
+ this.intStack[this.intPtr] += this.identifierLengthStack[this.identifierLengthPtr];
+}
protected void consumeAssertStatement() {
// AssertStatement ::= 'assert' Expression ':' Expression ';'
this.expressionLengthPtr-=2;
pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));
}
-
protected void consumeAssignment() {
// Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
//optimize the push/pop
@@ -979,6 +1356,133 @@ protected void consumeBinaryExpression(int op) {
op);
}
break;
+ case LESS :
+ this.intPtr--;
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ break;
+ default :
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ }
+}
+/**
+ * @param op binary operator
+ */
+protected void consumeBinaryExpressionWithName(int op) {
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ /*
+ if (op == OR_OR) {
+ this.expressionStack[this.expressionPtr] =
+ new OR_OR_Expression(
+ this.expressionStack[this.expressionPtr + 1],
+ this.expressionStack[this.expressionPtr],
+ op);
+ } else {
+ if (op == AND_AND) {
+ this.expressionStack[this.expressionPtr] =
+ new AND_AND_Expression(
+ this.expressionStack[this.expressionPtr + 1],
+ this.expressionStack[this.expressionPtr],
+ op);
+ } else {
+ // look for "string1" + "string2"
+ if ((op == PLUS) && this.optimizeStringLiterals) {
+ Expression expr1, expr2;
+ expr1 = this.expressionStack[this.expressionPtr + 1];
+ expr2 = this.expressionStack[this.expressionPtr];
+ if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof CharLiteral) { // string+char
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
+ } else if (expr2 instanceof StringLiteral) { //string+string
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
+ } else {
+ this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else {
+ this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ this.expressionStack[this.expressionPtr + 1],
+ this.expressionStack[this.expressionPtr],
+ op);
+ }
+ }
+ }
+ */
+ Expression expr1 = this.expressionStack[this.expressionPtr + 1];
+ Expression expr2 = this.expressionStack[this.expressionPtr];
+ switch(op) {
+ case OR_OR :
+ this.expressionStack[this.expressionPtr] =
+ new OR_OR_Expression(
+ expr1,
+ expr2,
+ op);
+ break;
+ case AND_AND :
+ this.expressionStack[this.expressionPtr] =
+ new AND_AND_Expression(
+ expr1,
+ expr2,
+ op);
+ break;
+ case PLUS :
+ // look for "string1" + "string2"
+ if (this.optimizeStringLiterals) {
+ if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof CharLiteral) { // string+char
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
+ } else if (expr2 instanceof StringLiteral) { //string+string
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
+ } else {
+ this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else {
+ this.expressionStack[this.expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof StringLiteral) {
+ // string + string
+ this.expressionStack[this.expressionPtr] =
+ ((StringLiteral) expr1).extendsWith((StringLiteral) expr2);
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ }
+ } else {
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ }
+ break;
+ case LESS :
+ this.intPtr--;
+ this.expressionStack[this.expressionPtr] =
+ new BinaryExpression(
+ expr1,
+ expr2,
+ op);
+ break;
default :
this.expressionStack[this.expressionPtr] =
new BinaryExpression(
@@ -1026,21 +1530,6 @@ protected void consumeCaseLabel() {
Expression expression = this.expressionStack[this.expressionPtr--];
pushOnAstStack(new CaseStatement(expression, expression.sourceEnd, this.intStack[this.intPtr--]));
}
-protected void consumeCastExpression() {
- // CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
- // CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
-
- //this.intStack : posOfLeftParen dim posOfRightParen
-
- //optimize the push/pop
-
- Expression exp, cast, castType;
- int end = this.intStack[this.intPtr--];
- this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
- castType.sourceEnd = end - 1;
- castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
- cast.sourceEnd = exp.sourceEnd;
-}
protected void consumeCastExpressionLL1() {
//CastExpression ::= '(' Expression ')' InsideCastExpressionLL1 UnaryExpressionNotPlusMinus
// Expression is used in order to make the grammar LL1
@@ -1057,35 +1546,152 @@ protected void consumeCastExpressionLL1() {
updateSourcePosition(cast);
cast.sourceEnd=exp.sourceEnd;
}
-protected void consumeCatches() {
- // Catches ::= Catches CatchClause
- optimizedConcatNodeLists();
+protected void consumeCastExpressionWithGenericsArray() {
+ // CastExpression ::= PushLPAREN Name TypeArguments Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+
+ Expression exp, cast, castType;
+ int end = this.intStack[this.intPtr--];
+
+ int dim = this.intStack[this.intPtr--];
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+
+ this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(dim));
+ intPtr--;
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+ cast.sourceEnd = exp.sourceEnd;
}
-protected void consumeCatchHeader() {
- // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+protected void consumeCastExpressionWithNameArray() {
+ // CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
- if (this.currentElement == null){
- return; // should never occur, this consumeRule is only used in recovery mode
- }
- // current element should be a block due to the presence of the opening brace
- if (!(this.currentElement instanceof RecoveredBlock)){
- if(!(this.currentElement instanceof RecoveredMethod)) {
- return;
- }
- RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
- if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
- return;
- }
- }
+ Expression exp, cast, castType;
+ int end = this.intStack[this.intPtr--];
- Argument arg = (Argument)this.astStack[this.astPtr--];
- // convert argument to local variable
- LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
- localDeclaration.type = arg.type;
- localDeclaration.declarationSourceStart = arg.declarationSourceStart;
- localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+ // handle type arguments
+ pushOnGenericsLengthStack(0);
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
- this.currentElement = this.currentElement.add(localDeclaration, 0);
+ this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+ cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCastExpressionWithPrimitiveType() {
+ // CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
+
+ //this.intStack : posOfLeftParen dim posOfRightParen
+
+ //optimize the push/pop
+
+ Expression exp, cast, castType;
+ int end = this.intStack[this.intPtr--];
+ this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = getTypeReference(this.intStack[this.intPtr--]));
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+ cast.sourceEnd = exp.sourceEnd;
+}
+protected ParameterizedQualifiedTypeReference computeQualifiedGenericsFromRightSide(TypeReference rightSide, int dim) {
+ int nameSize = this.identifierLengthStack[this.identifierLengthPtr];
+ int tokensSize = nameSize;
+ if (rightSide instanceof ParameterizedSingleTypeReference) {
+ tokensSize ++;
+ } else if (rightSide instanceof SingleTypeReference) {
+ tokensSize ++;
+ } else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
+ tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
+ } else if (rightSide instanceof QualifiedTypeReference) {
+ tokensSize += ((QualifiedTypeReference) rightSide).tokens.length;
+ }
+ TypeReference[][] typeArguments = new TypeReference[tokensSize][];
+ char[][] tokens = new char[tokensSize][];
+ long[] positions = new long[tokensSize];
+ if (rightSide instanceof ParameterizedSingleTypeReference) {
+ ParameterizedSingleTypeReference singleParameterizedTypeReference = (ParameterizedSingleTypeReference) rightSide;
+ tokens[nameSize] = singleParameterizedTypeReference.token;
+ positions[nameSize] = (((long) singleParameterizedTypeReference.sourceStart) << 32) + singleParameterizedTypeReference.sourceEnd;
+ typeArguments[nameSize] = singleParameterizedTypeReference.typeArguments;
+ } else if (rightSide instanceof SingleTypeReference) {
+ SingleTypeReference singleTypeReference = (SingleTypeReference) rightSide;
+ tokens[nameSize] = singleTypeReference.token;
+ positions[nameSize] = (((long) singleTypeReference.sourceStart) << 32) + singleTypeReference.sourceEnd;
+ } else if (rightSide instanceof ParameterizedQualifiedTypeReference) {
+ ParameterizedQualifiedTypeReference parameterizedTypeReference = (ParameterizedQualifiedTypeReference) rightSide;
+ TypeReference[][] rightSideTypeArguments = parameterizedTypeReference.typeArguments;
+ System.arraycopy(rightSideTypeArguments, 0, typeArguments, nameSize, rightSideTypeArguments.length);
+ char[][] rightSideTokens = parameterizedTypeReference.tokens;
+ System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
+ long[] rightSidePositions = parameterizedTypeReference.sourcePositions;
+ System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
+ } else if (rightSide instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) rightSide;
+ char[][] rightSideTokens = qualifiedTypeReference.tokens;
+ System.arraycopy(rightSideTokens, 0, tokens, nameSize, rightSideTokens.length);
+ long[] rightSidePositions = qualifiedTypeReference.sourcePositions;
+ System.arraycopy(rightSidePositions, 0, positions, nameSize, rightSidePositions.length);
+ }
+
+ int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+ TypeReference[] currentTypeArguments = new TypeReference[currentTypeArgumentsLength];
+ this.genericsPtr -= currentTypeArgumentsLength;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, currentTypeArguments, 0, currentTypeArgumentsLength);
+
+ if (nameSize == 1) {
+ tokens[0] = this.identifierStack[this.identifierPtr];
+ positions[0] = this.identifierPositionStack[this.identifierPtr--];
+ typeArguments[0] = currentTypeArguments;
+ } else {
+ this.identifierPtr -= nameSize;
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, nameSize);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, nameSize);
+ typeArguments[nameSize - 1] = currentTypeArguments;
+ }
+ this.identifierLengthPtr--;
+ return new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, positions);
+}
+protected void consumeCastExpressionWithQualifiedGenericsArray() {
+ // CastExpression ::= PushLPAREN Name OnlyTypeArguments '.' ClassOrInterfaceType Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
+ Expression exp, cast, castType;
+ int end = this.intStack[this.intPtr--];
+
+ int dim = this.intStack[this.intPtr--];
+ TypeReference rightSide = getTypeReference(0);
+
+ ParameterizedQualifiedTypeReference qualifiedParameterizedTypeReference = computeQualifiedGenericsFromRightSide(rightSide, dim);
+ intPtr--;
+ this.expressionStack[this.expressionPtr] = cast = new CastExpression(exp = this.expressionStack[this.expressionPtr], castType = qualifiedParameterizedTypeReference);
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = (cast.sourceStart = this.intStack[this.intPtr--]) + 1;
+ cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCatches() {
+ // Catches ::= Catches CatchClause
+ optimizedConcatNodeLists();
+}
+protected void consumeCatchHeader() {
+ // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+
+ if (this.currentElement == null){
+ return; // should never occur, this consumeRule is only used in recovery mode
+ }
+ // current element should be a block due to the presence of the opening brace
+ if (!(this.currentElement instanceof RecoveredBlock)){
+ if(!(this.currentElement instanceof RecoveredMethod)) {
+ return;
+ }
+ RecoveredMethod rMethod = (RecoveredMethod) this.currentElement;
+ if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
+ return;
+ }
+ }
+
+ Argument arg = (Argument)this.astStack[this.astPtr--];
+ // convert argument to local variable
+ LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
+ localDeclaration.type = arg.type;
+ localDeclaration.declarationSourceStart = arg.declarationSourceStart;
+ localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+
+ this.currentElement = this.currentElement.add(localDeclaration, 0);
this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
this.restartRecovery = true; // request to restart from here on
this.lastIgnoredToken = -1;
@@ -1123,7 +1729,7 @@ protected void consumeClassBodyDeclarationsopt() {
protected void consumeClassBodyopt() {
// ClassBodyopt ::= $empty
pushOnAstStack(null);
- this.endPosition = this.scanner.startPosition - 1;
+ this.endPosition = this.rParenPos;
}
protected void consumeClassDeclaration() {
// ClassDeclaration ::= ClassHeader ClassBody
@@ -1144,19 +1750,22 @@ protected void consumeClassDeclaration() {
boolean hasConstructor = typeDecl.checkConstructors(this);
//add the default constructor when needed (interface don't have it)
- if (!hasConstructor && !typeDecl.isInterface()) {
- boolean insideFieldInitializer = false;
- if (this.diet) {
- for (int i = this.nestedType; i > 0; i--){
- if (this.variablesCounter[i] > 0) {
- insideFieldInitializer = true;
- break;
+ if (!hasConstructor) {
+ switch(typeDecl.kind()) {
+ case IGenericType.CLASS_DECL :
+ case IGenericType.ENUM_DECL :
+ boolean insideFieldInitializer = false;
+ if (this.diet) {
+ for (int i = this.nestedType; i > 0; i--){
+ if (this.variablesCounter[i] > 0) {
+ insideFieldInitializer = true;
+ break;
+ }
+ }
}
- }
+ typeDecl.createDefaultConstructor(!this.diet || insideFieldInitializer, true);
}
- typeDecl.createsInternalConstructor(!this.diet || insideFieldInitializer, true);
}
-
//always add (will be remove at code gen time if empty)
if (this.scanner.containsAssertKeyword) {
typeDecl.bits |= ASTNode.AddAssertionMASK;
@@ -1184,10 +1793,12 @@ protected void consumeClassHeader() {
}
protected void consumeClassHeaderExtends() {
// ClassHeaderExtends ::= 'extends' ClassType
+ //superclass
+ TypeReference superClass = getTypeReference(0);
// There is a class declaration on the top of stack
TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
- //superclass
- typeDecl.superclass = getTypeReference(0);
+ typeDecl.superclass = superClass;
+ superClass.bits |= ASTNode.IsSuperType;
typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1;
// recovery
if (this.currentElement != null){
@@ -1207,6 +1818,9 @@ protected void consumeClassHeaderImplements() {
typeDecl.superInterfaces = new TypeReference[length],
0,
length);
+ for (int i = 0, max = typeDecl.superInterfaces.length; i < max; i++) {
+ typeDecl.superInterfaces[i].bits |= ASTNode.IsSuperType;
+ }
typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
this.listLength = 0; // reset after having read super-interfaces
// recovery
@@ -1214,8 +1828,8 @@ protected void consumeClassHeaderImplements() {
this.lastCheckPoint = typeDecl.bodyStart;
}
}
-protected void consumeClassHeaderName() {
- // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+protected void consumeClassHeaderName1() {
+ // ClassHeaderName1 ::= Modifiersopt 'class' 'Identifier'
TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
if (this.nestedMethod[this.nestedType] == 0) {
if (this.nestedType != 0) {
@@ -1247,6 +1861,16 @@ protected void consumeClassHeaderName() {
if (typeDecl.modifiersSourceStart >= 0) {
typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
}
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ typeDecl.annotations = new Annotation[length],
+ 0,
+ length);
+ }
typeDecl.bodyStart = typeDecl.sourceEnd + 1;
pushOnAstStack(typeDecl);
@@ -1261,6 +1885,24 @@ protected void consumeClassHeaderName() {
typeDecl.javadoc = this.javadoc;
this.javadoc = null;
}
+protected void consumeTypeHeaderNameWithTypeParameters() {
+ // ClassHeaderName ::= ClassHeaderName1 TypeParameters
+ // InterfaceHeaderName ::= InterfaceHeaderName1 TypeParameters
+ TypeDeclaration typeDecl = (TypeDeclaration)this.astStack[this.astPtr];
+
+ // consume type parameters
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
+
+ typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
+
+ this.listTypeParameterLength = 0;
+
+ if (this.currentElement != null) { // is recovering
+ this.lastCheckPoint = typeDecl.bodyStart;
+ }
+}
protected void consumeClassInstanceCreationExpression() {
// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
classInstanceCreation(false);
@@ -1272,8 +1914,71 @@ protected void consumeClassInstanceCreationExpressionName() {
protected void consumeClassInstanceCreationExpressionQualified() {
// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
// ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+ classInstanceCreation(true);
+
+ this.expressionLengthPtr--;
+ QualifiedAllocationExpression qae =
+ (QualifiedAllocationExpression) this.expressionStack[this.expressionPtr--];
+ qae.enclosingInstance = this.expressionStack[this.expressionPtr];
+ this.expressionStack[this.expressionPtr] = qae;
+ qae.sourceStart = qae.enclosingInstance.sourceStart;
+}
+protected void consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() {
+ // ClassInstanceCreationExpression ::= Primary '.' 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+ // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' TypeArguments SimpleName '(' ArgumentListopt ')' ClassBodyopt
+
+ QualifiedAllocationExpression alloc;
+ int length;
+ if (((length = this.astLengthStack[this.astLengthPtr--]) == 1) && (this.astStack[this.astPtr] == null)) {
+ //NO ClassBody
+ this.astPtr--;
+ alloc = new QualifiedAllocationExpression();
+ alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ alloc.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ alloc.type = getTypeReference(0);
+
+ length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+ intPtr--;
+
+ //the default constructor with the correct number of argument
+ //will be created and added by the TC (see createsInternalConstructorWithBinding)
+ alloc.sourceStart = this.intStack[this.intPtr--];
+ pushOnExpressionStack(alloc);
+ } else {
+ dispatchDeclarationInto(length);
+ TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
+ anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
+ anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
+ if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+ anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+ }
+ this.astPtr--;
+ this.astLengthPtr--;
- classInstanceCreation(true); // <-- push the Qualifed....
+ QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
+ if (allocationExpression != null) {
+ allocationExpression.sourceEnd = this.endStatementPosition;
+ // handle type arguments
+ length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
+ allocationExpression.sourceStart = intStack[intPtr--];
+ }
+
+ // mark initializers with local type mark if needed
+ markInitializersWithLocalType(anonymousTypeDeclaration);
+ }
this.expressionLengthPtr--;
QualifiedAllocationExpression qae =
@@ -1282,10 +1987,74 @@ protected void consumeClassInstanceCreationExpressionQualified() {
this.expressionStack[this.expressionPtr] = qae;
qae.sourceStart = qae.enclosingInstance.sourceStart;
}
+protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
+ // ClassInstanceCreationExpression ::= 'new' TypeArguments ClassType '(' ArgumentListopt ')' ClassBodyopt
+ AllocationExpression alloc;
+ int length;
+ if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
+ && (this.astStack[this.astPtr] == null)) {
+ //NO ClassBody
+ this.astPtr--;
+ alloc = new AllocationExpression();
+ alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
+
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ alloc.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ alloc.type = getTypeReference(0);
+
+ length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, alloc.typeArguments = new TypeReference[length], 0, length);
+ intPtr--;
+
+ //the default constructor with the correct number of argument
+ //will be created and added by the TC (see createsInternalConstructorWithBinding)
+ alloc.sourceStart = this.intStack[this.intPtr--];
+ pushOnExpressionStack(alloc);
+ } else {
+ dispatchDeclarationInto(length);
+ TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)this.astStack[this.astPtr];
+ anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
+ anonymousTypeDeclaration.bodyEnd = this.endStatementPosition;
+ if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+ anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+ }
+ this.astPtr--;
+ this.astLengthPtr--;
+
+ QualifiedAllocationExpression allocationExpression = anonymousTypeDeclaration.allocation;
+ if (allocationExpression != null) {
+ allocationExpression.sourceEnd = this.endStatementPosition;
+ // handle type arguments
+ length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, allocationExpression.typeArguments = new TypeReference[length], 0, length);
+ allocationExpression.sourceStart = intStack[intPtr--];
+ }
+
+ // mark initializers with local type mark if needed
+ markInitializersWithLocalType(anonymousTypeDeclaration);
+ }
+}
+protected void consumeClassOrInterface() {
+ this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] += this.identifierLengthStack[this.identifierLengthPtr];
+ pushOnGenericsLengthStack(0); // handle type arguments
+}
+protected void consumeClassOrInterfaceName() {
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0); // handle type arguments
+}
protected void consumeClassTypeElt() {
// ClassTypeElt ::= ClassType
pushOnAstStack(getTypeReference(0));
- /* if incomplete thrown exception list, listLength counter will not have been reset,
+ /* if incomplete thrown exception list, this.listLength counter will not have been reset,
indicating that some items are available on the stack */
this.listLength++;
}
@@ -1294,13 +2063,13 @@ protected void consumeClassTypeList() {
optimizedConcatNodeLists();
}
protected void consumeCompilationUnit() {
- // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+ // CompilationUnit ::= EnterCompilationUnit InternalCompilationUnit
// do nothing by default
}
protected void consumeConditionalExpression(int op) {
// ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
//optimize the push/pop
-
+ this.intPtr -= 2;//consume position of the question mark
this.expressionPtr -= 2;
this.expressionLengthPtr -= 2;
this.expressionStack[this.expressionPtr] =
@@ -1309,6 +2078,21 @@ protected void consumeConditionalExpression(int op) {
this.expressionStack[this.expressionPtr + 1],
this.expressionStack[this.expressionPtr + 2]);
}
+/**
+ * @param op
+ */
+protected void consumeConditionalExpressionWithName(int op) {
+ // ConditionalExpression ::= Name '?' Expression ':' ConditionalExpression
+ this.intPtr -= 2;//consume position of the question mark
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ this.expressionPtr -= 2;
+ this.expressionLengthPtr -= 2;
+ this.expressionStack[this.expressionPtr] =
+ new ConditionalExpression(
+ this.expressionStack[this.expressionPtr + 2],
+ this.expressionStack[this.expressionPtr],
+ this.expressionStack[this.expressionPtr + 1]);
+}
protected void consumeConstructorBlockStatements() {
// ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation BlockStatements '}'
concatNodeLists(); // explictly add the first statement into the list of statements
@@ -1322,11 +2106,11 @@ protected void consumeConstructorDeclaration() {
// ConstructorDeclaration ::= ConstructorHeader ConstructorBody
/*
- astStack : MethodDeclaration statements
- identifierStack : name
+ this.astStack : MethodDeclaration statements
+ this.identifierStack : name
==>
- astStack : MethodDeclaration
- identifierStack :
+ this.astStack : MethodDeclaration
+ this.identifierStack :
*/
//must provide a default constructor call when needed
@@ -1396,23 +2180,11 @@ protected void consumeConstructorDeclaration() {
}
//watch for } that could be given as a unicode ! ( u007D is '}' )
- // store the endPosition (position just before the '}') in case there is
+ // store the this.endPosition (position just before the '}') in case there is
// a trailing comment behind the end of the method
cd.bodyEnd = this.endPosition;
cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
}
-
-protected void consumeInvalidConstructorDeclaration() {
- // ConstructorDeclaration ::= ConstructorHeader ';'
- // now we know that the top of stack is a constructorDeclaration
- ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
-
- cd.bodyEnd = this.endPosition; // position just before the trailing semi-colon
- cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
- // report the problem and continue the parsing - narrowing the problem onto the method
-
- cd.modifiers |= AccSemicolonBody; // remember semi-colon body
-}
protected void consumeConstructorHeader() {
// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
@@ -1456,6 +2228,73 @@ protected void consumeConstructorHeaderName() {
//modifiers
cd.declarationSourceStart = this.intStack[this.intPtr--];
cd.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ cd.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+ // javadoc
+ cd.javadoc = this.javadoc;
+ this.javadoc = null;
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSource >>> 32);
+ pushOnAstStack(cd);
+ cd.sourceEnd = this.lParenPos;
+ cd.bodyStart = this.lParenPos+1;
+ this.listLength = 0; // initialize this.listLength before reading parameters/throws
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = cd.bodyStart;
+ if ((this.currentElement instanceof RecoveredType && this.lastIgnoredToken != TokenNameDOT)
+ || cd.modifiers != 0){
+ this.currentElement = this.currentElement.add(cd, 0);
+ this.lastIgnoredToken = -1;
+ }
+ }
+}
+protected void consumeConstructorHeaderNameWithTypeParameters() {
+
+ /* recovering - might be an empty message send */
+ if (this.currentElement != null){
+ if (this.lastIgnoredToken == TokenNamenew){ // was an allocation expression
+ this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
+ this.restartRecovery = true;
+ return;
+ }
+ }
+
+ // ConstructorHeaderName ::= Modifiersopt TypeParameters 'Identifier' '('
+ ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = this.identifierStack[this.identifierPtr];
+ long selectorSource = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ // consume type parameters
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, cd.typeParameters = new TypeParameter[length], 0, length);
+
+ //modifiers
+ cd.declarationSourceStart = this.intStack[this.intPtr--];
+ cd.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ cd.annotations = new Annotation[length],
+ 0,
+ length);
+ }
// javadoc
cd.javadoc = this.javadoc;
this.javadoc = null;
@@ -1465,7 +2304,7 @@ protected void consumeConstructorHeaderName() {
pushOnAstStack(cd);
cd.sourceEnd = this.lParenPos;
cd.bodyStart = this.lParenPos+1;
- this.listLength = 0; // initialize listLength before reading parameters/throws
+ this.listLength = 0; // initialize this.listLength before reading parameters/throws
// recovery
if (this.currentElement != null){
@@ -1487,6 +2326,7 @@ protected void consumeDefaultModifiers() {
pushOnIntStack(
this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition);
resetModifiers();
+ pushOnExpressionStackLengthStack(0); // no annotation
}
protected void consumeDiet() {
// Diet ::= $empty
@@ -1513,11 +2353,19 @@ protected void consumeDimWithOrWithOutExprs() {
// DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
concatExpressionLists();
}
+protected void consumeEmptyAnnotationTypeMemberDeclarationsopt() {
+ // AnnotationTypeMemberDeclarationsopt ::= $empty
+ pushOnAstLengthStack(0);
+}
protected void consumeEmptyArgumentListopt() {
// ArgumentListopt ::= $empty
pushOnExpressionStackLengthStack(0);
}
-protected void consumeEmptyArrayInitializer() {
+protected void consumeEmptyArguments() {
+ // Argumentsopt ::= $empty
+ pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyArrayInitializer() {
// ArrayInitializer ::= '{' ,opt '}'
arrayInitializer(0);
}
@@ -1543,10 +2391,21 @@ protected void consumeEmptyClassMemberDeclaration() {
problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
flushCommentsDefinedPriorTo(this.endStatementPosition);
}
+protected void consumeEmptyMethodHeaderDefaultValue() {
+ // DefaultValueopt ::= $empty
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
+ if(method.isAnnotationMethod()) { //'method' can be a MethodDeclaration when recovery is started
+ pushOnExpressionStackLengthStack(0);
+ }
+}
protected void consumeEmptyDimsopt() {
// Dimsopt ::= $empty
pushOnIntStack(0);
}
+protected void consumeEmptyEnumDeclarations() {
+ // EnumBodyDeclarationsopt ::= $empty
+ pushOnAstLengthStack(0);
+}
protected void consumeEmptyExpression() {
// Expressionopt ::= $empty
pushOnExpressionStackLengthStack(0);
@@ -1559,10 +2418,6 @@ protected void consumeEmptyForUpdateopt() {
// ForUpdateopt ::= $empty
pushOnExpressionStackLengthStack(0);
}
-protected void consumeEmptyImportDeclarationsopt() {
- // ImportDeclarationsopt ::= $empty
- pushOnAstLengthStack(0);
-}
protected void consumeEmptyInterfaceMemberDeclaration() {
// InterfaceMemberDeclaration ::= ';'
pushOnAstLengthStack(0);
@@ -1571,6 +2426,19 @@ protected void consumeEmptyInterfaceMemberDeclarationsopt() {
// InterfaceMemberDeclarationsopt ::= $empty
pushOnAstLengthStack(0);
}
+protected void consumeEmptyInternalCompilationUnit() {
+ // InternalCompilationUnit ::= $empty
+ // nothing to do by default
+}
+protected void consumeEmptyMemberValuePairsopt() {
+ // MemberValuePairsopt ::= $empty
+ pushOnAstLengthStack(0);
+}
+protected void consumeEmptyMemberValueArrayInitializer() {
+ // MemberValueArrayInitializer ::= '{' ',' '}'
+ // MemberValueArrayInitializer ::= '{' '}'
+ arrayInitializer(0);
+}
protected void consumeEmptyStatement() {
// EmptyStatement ::= ';'
if (this.scanner.source[this.endStatementPosition] == ';') {
@@ -1590,17 +2458,132 @@ protected void consumeEmptyTypeDeclaration() {
problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
flushCommentsDefinedPriorTo(this.endStatementPosition);
}
-protected void consumeEmptyTypeDeclarationsopt() {
- // TypeDeclarationsopt ::= $empty
- pushOnAstLengthStack(0);
+protected void consumeEnhancedForStatementHeader(boolean hasModifiers){
+ // EnhancedForStatementHeader ::= 'for' '(' Type PushModifiers Identifier Dimsopt ':' Expression ')'
+ // EnhancedForStatementHeader ::= 'for' '(' Modifiers Type PushRealModifiers Identifier Dimsopt ':' Expression ')'
+ TypeReference type;
+
+ char[] identifierName = this.identifierStack[this.identifierPtr];
+ long namePosition = this.identifierPositionStack[this.identifierPtr];
+
+ LocalDeclaration localDeclaration = createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
+ localDeclaration.declarationSourceEnd = localDeclaration.declarationEnd;
+
+ int extraDims = this.intStack[this.intPtr--];
+ this.identifierPtr--;
+ this.identifierLengthPtr--;
+ // remove fake modifiers/modifiers start
+ int declarationSourceStart = 0;
+ int modifiersValue = 0;
+ if (hasModifiers) {
+ declarationSourceStart = this.intStack[this.intPtr--];
+ modifiersValue = this.intStack[this.intPtr--];
+ } else {
+ this.intPtr-=2;
+ }
+
+ //updates are on the expression stack
+ this.expressionLengthPtr--;
+ Expression collection = this.expressionStack[this.expressionPtr--];
+
+ type = getTypeReference(this.intStack[this.intPtr--] + extraDims); // type dimension
+
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--])!= 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ localDeclaration.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+ if (hasModifiers) {
+ localDeclaration.declarationSourceStart = declarationSourceStart;
+ localDeclaration.modifiers = modifiersValue;
+ } else {
+ localDeclaration.declarationSourceStart = type.sourceStart;
+ }
+ localDeclaration.type = type;
+
+ ForeachStatement iteratorForStatement =
+ new ForeachStatement(
+ localDeclaration,
+ collection,
+ this.intStack[this.intPtr--]);
+ pushOnAstStack(iteratorForStatement);
+
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfForeachStatements(localDeclaration, collection);
+ }
+}
+protected void consumeEnhancedForStatement() {
+ // EnhancedForStatement ::= EnhancedForStatementHeader Statement
+ // EnhancedForStatementNoShortIf ::= EnhancedForStatementHeader StatementNoShortIf
+
+ //statements
+ this.astLengthPtr--;
+ Statement statement = (Statement) this.astStack[this.astPtr--];
+
+ // foreach statement is on the ast stack
+ ForeachStatement foreachStatement = (ForeachStatement) this.astStack[this.astPtr];
+ foreachStatement.action = statement;
+ // remember useful empty statement
+ if (statement instanceof EmptyStatement) statement.bits |= ASTNode.IsUsefulEmptyStatementMASK;
+
+ foreachStatement.sourceEnd = this.endStatementPosition;
}
protected void consumeEnterAnonymousClassBody() {
// EnterAnonymousClassBody ::= $empty
- QualifiedAllocationExpression alloc;
+ TypeReference typeReference = getTypeReference(0);
+
+ TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
+ anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+ anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+ QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
+ markEnclosingMemberWithLocalType();
+ pushOnAstStack(anonymousType);
+
+ alloc.sourceEnd = this.rParenPos; //the position has been stored explicitly
+ int argumentLength;
+ if ((argumentLength = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= argumentLength;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ alloc.arguments = new Expression[argumentLength],
+ 0,
+ argumentLength);
+ }
+ alloc.type = typeReference;
+
+ anonymousType.sourceEnd = alloc.sourceEnd;
+ //position at the type while it impacts the anonymous declaration
+ anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+ alloc.sourceStart = this.intStack[this.intPtr--];
+ pushOnExpressionStack(alloc);
+
+ anonymousType.bodyStart = this.scanner.currentPosition;
+ this.listLength = 0; // will be updated when reading super-interfaces
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = anonymousType.bodyStart;
+ this.currentElement = this.currentElement.add(anonymousType, 0);
+ this.currentToken = 0; // opening brace already taken into account
+ this.lastIgnoredToken = -1;
+ }
+}
+protected void consumeEnterAnonymousClassBodySimpleName() {
+ // EnterAnonymousClassBody ::= $empty
+ pushOnGenericsLengthStack(0);
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ TypeReference typeReference = getTypeReference(0);
+
TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
- alloc = anonymousType.allocation = new QualifiedAllocationExpression(anonymousType);
+ QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
markEnclosingMemberWithLocalType();
pushOnAstStack(anonymousType);
@@ -1615,7 +2598,7 @@ protected void consumeEnterAnonymousClassBody() {
0,
argumentLength);
}
- alloc.type = getTypeReference(0);
+ alloc.type = typeReference;
anonymousType.sourceEnd = alloc.sourceEnd;
//position at the type while it impacts the anonymous declaration
@@ -1667,6 +2650,16 @@ protected void consumeEnterVariable() {
if (isLocalDeclaration) {
declaration.declarationSourceStart = this.intStack[this.intPtr--];
declaration.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ declaration.annotations = new Annotation[length],
+ 0,
+ length);
+ }
type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
if (declaration.declarationSourceStart == -1) {
// this is true if there is no modifiers for the local variable declaration
@@ -1678,7 +2671,16 @@ protected void consumeEnterVariable() {
pushOnAstStack(type);
declaration.declarationSourceStart = this.intStack[this.intPtr--];
declaration.modifiers = this.intStack[this.intPtr--];
-
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ declaration.annotations = new Annotation[length],
+ 0,
+ length);
+ }
// Store javadoc only on first declaration as it is the same for all ones
FieldDeclaration fieldDeclaration = (FieldDeclaration) declaration;
fieldDeclaration.javadoc = this.javadoc;
@@ -1697,7 +2699,7 @@ protected void consumeEnterVariable() {
declaration.type = type;
} else {
int dimension = typeDim + extendedDimension;
- //on the identifierLengthStack there is the information about the type....
+ //on the this.identifierLengthStack there is the information about the type....
int baseType;
if ((baseType = this.identifierLengthStack[this.identifierLengthPtr + 1]) < 0) {
//it was a baseType
@@ -1736,6 +2738,275 @@ protected void consumeEnterVariable() {
this.lastIgnoredToken = -1;
}
}
+protected void consumeEnumBodyNoConstants() {
+ // nothing to do
+ // The 0 on the astLengthStack has been pushed by EnumBodyDeclarationsopt
+}
+protected void consumeEnumBodyWithConstants() {
+ // merge the constants values with the class body
+ concatNodeLists();
+}
+protected void consumeEnumConstantHeaderName() {
+ if (this.currentElement != null) {
+ if (!(this.currentElement instanceof RecoveredType
+ || (this.currentElement instanceof RecoveredField && ((RecoveredField)currentElement).fieldDeclaration.type == null))
+ || (this.lastIgnoredToken == TokenNameDOT)) {
+ this.lastCheckPoint = this.scanner.startPosition;
+ this.restartRecovery = true;
+ return;
+ }
+ }
+ long namePosition = this.identifierPositionStack[this.identifierPtr];
+ char[] constantName = this.identifierStack[this.identifierPtr--];
+ final int sourceEnd = (int) namePosition;
+ FieldDeclaration enumConstant = createFieldDeclaration(constantName, (int) (namePosition >>> 32), sourceEnd);
+ this.identifierLengthPtr--;
+ enumConstant.modifiersSourceStart = this.intStack[this.intPtr--];
+ enumConstant.modifiers = this.intStack[this.intPtr--];
+ enumConstant.declarationSourceStart = enumConstant.modifiersSourceStart;
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ enumConstant.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+ pushOnAstStack(enumConstant);
+ if (this.currentElement != null){
+ this.lastCheckPoint = enumConstant.sourceEnd + 1;
+ this.currentElement = this.currentElement.add(enumConstant, 0);
+ }
+ // javadoc
+ enumConstant.javadoc = this.javadoc;
+ this.javadoc = null;
+}
+protected void consumeEnumConstantHeader() {
+ FieldDeclaration enumConstant = (FieldDeclaration) this.astStack[this.astPtr];
+ boolean foundOpeningBrace = this.currentToken == TokenNameLBRACE;
+ if (foundOpeningBrace){
+ // qualified allocation expression
+ TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
+ anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+ anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+ final int start = this.scanner.startPosition;
+ anonymousType.declarationSourceStart = start;
+ anonymousType.sourceStart = start;
+ anonymousType.sourceEnd = start; // closing parenthesis
+ anonymousType.modifiers = 0;
+ anonymousType.bodyStart = this.scanner.currentPosition;
+ markEnclosingMemberWithLocalType();
+ pushOnAstStack(anonymousType);
+ QualifiedAllocationExpression allocationExpression = new QualifiedAllocationExpression(anonymousType);
+ allocationExpression.enumConstant = enumConstant;
+
+ // fill arguments if needed
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ allocationExpression.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ enumConstant.initialization = allocationExpression;
+ } else {
+ AllocationExpression allocationExpression = new AllocationExpression();
+ allocationExpression.enumConstant = enumConstant;
+ // fill arguments if needed
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ allocationExpression.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ enumConstant.initialization = allocationExpression;
+ }
+
+ // recovery
+ if (this.currentElement != null) {
+ if(foundOpeningBrace) {
+ TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr];
+ this.currentElement = this.currentElement.add(anonymousType, 0);
+ this.lastCheckPoint = anonymousType.bodyStart;
+ this.lastIgnoredToken = -1;
+ this.currentToken = 0; // opening brace already taken into account
+ } else {
+ if(this.currentToken == TokenNameSEMICOLON) {
+ RecoveredType currentType = this.currentRecoveryType();
+ if(currentType != null) {
+ currentType.insideEnumConstantPart = false;
+ }
+ }
+ if (!(this.currentElement instanceof RecoveredType)
+ && (this.currentToken == TokenNameDOT)){
+ this.lastCheckPoint = enumConstant.sourceStart;
+ this.restartRecovery = true;
+ return;
+ }
+ this.lastCheckPoint = this.scanner.startPosition; // force to restart at this exact position
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true;
+ }
+ }
+}
+protected void consumeEnumConstantNoClassBody() {
+ // set declarationEnd and declarationSourceEnd
+ final FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr];
+ int declarationEnd = fieldDeclaration.sourceEnd;
+ if (declarationEnd > rParenPos) {
+ fieldDeclaration.declarationEnd = declarationEnd;
+ fieldDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(declarationEnd);
+ } else {
+ fieldDeclaration.declarationEnd = rParenPos;
+ fieldDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(rParenPos);
+ }
+}
+protected void consumeEnumConstants() {
+ concatNodeLists();
+}
+protected void consumeEnumConstantWithClassBody() {
+ dispatchDeclarationInto(this.astLengthStack[this.astLengthPtr--]);
+ TypeDeclaration anonymousType = (TypeDeclaration) this.astStack[this.astPtr--]; // pop type
+ this.astLengthPtr--;
+ anonymousType.bodyEnd = this.endPosition;
+ anonymousType.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+ final FieldDeclaration fieldDeclaration = ((FieldDeclaration) this.astStack[this.astPtr]);
+ fieldDeclaration.declarationEnd = this.endStatementPosition;
+ fieldDeclaration.declarationSourceEnd = anonymousType.declarationSourceEnd;
+}
+protected void consumeEnumDeclaration() {
+ // EnumDeclaration ::= EnumHeader ClassHeaderImplementsopt EnumBody
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ //there are length declarations
+ //dispatch according to the type of the declarations
+ dispatchDeclarationIntoEnumDeclaration(length);
+ }
+
+ TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
+
+ // mark initializers with local type mark if needed
+ markInitializersWithLocalType(enumDeclaration);
+
+ //convert constructor that do not have the type's name into methods
+ boolean hasConstructor = enumDeclaration.checkConstructors(this);
+
+ //add the default constructor when needed
+ if (!hasConstructor) {
+ boolean insideFieldInitializer = false;
+ if (this.diet) {
+ for (int i = this.nestedType; i > 0; i--){
+ if (this.variablesCounter[i] > 0) {
+ insideFieldInitializer = true;
+ break;
+ }
+ }
+ }
+ enumDeclaration.createDefaultConstructor(!this.diet || insideFieldInitializer, true);
+ }
+
+ //always add (will be remove at code gen time if empty)
+ if (this.scanner.containsAssertKeyword) {
+ enumDeclaration.bits |= ASTNode.AddAssertionMASK;
+ }
+ enumDeclaration.addClinit();
+ enumDeclaration.bodyEnd = this.endStatementPosition;
+ if (length == 0 && !containsComment(enumDeclaration.bodyStart, enumDeclaration.bodyEnd)) {
+ enumDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+ }
+
+ enumDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeEnumDeclarations() {
+ // Do nothing by default
+}
+protected void consumeEnumHeader() {
+ TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+ if (this.currentToken == TokenNameLBRACE) {
+ typeDecl.bodyStart = this.scanner.currentPosition;
+ }
+
+ if (this.currentElement != null) {
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+
+ // flush the comments related to the enum header
+ this.scanner.commentPtr = -1;
+}
+protected void consumeEnumHeaderName() {
+ // EnumHeaderName ::= Modifiersopt 'enum' Identifier
+ TypeDeclaration enumDeclaration = new TypeDeclaration(this.compilationUnit.compilationResult);
+ if (this.nestedMethod[this.nestedType] == 0) {
+ if (this.nestedType != 0) {
+ enumDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+ }
+ } else {
+ // Record that the block has a declaration for local types
+// markEnclosingMemberWithLocalType();
+ blockReal();
+ }
+ //highlight the name of the type
+ long pos = this.identifierPositionStack[this.identifierPtr];
+ enumDeclaration.sourceEnd = (int) pos;
+ enumDeclaration.sourceStart = (int) (pos >>> 32);
+ enumDeclaration.name = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push two int positions: the beginning of the class token and its end.
+ // we want to keep the beginning position but get rid of the end position
+ // it is only used for the ClassLiteralAccess positions.
+ enumDeclaration.declarationSourceStart = this.intStack[this.intPtr--];
+ this.intPtr--; // remove the end position of the class token
+
+ enumDeclaration.modifiersSourceStart = this.intStack[this.intPtr--];
+ enumDeclaration.modifiers = this.intStack[this.intPtr--] | AccEnum;
+ if (enumDeclaration.modifiersSourceStart >= 0) {
+ enumDeclaration.declarationSourceStart = enumDeclaration.modifiersSourceStart;
+ }
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ enumDeclaration.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+// if (this.currentToken == TokenNameLBRACE) {
+// enumDeclaration.bodyStart = this.scanner.currentPosition;
+// }
+ enumDeclaration.bodyStart = enumDeclaration.sourceEnd + 1;
+ pushOnAstStack(enumDeclaration);
+
+ this.listLength = 0; // will be updated when reading super-interfaces
+
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ //TODO this code will be never run while 'enum' is an identifier in 1.3 scanner
+ this.problemReporter().invalidUsageOfEnumDeclarations(enumDeclaration);
+ }
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = enumDeclaration.bodyStart;
+ this.currentElement = this.currentElement.add(enumDeclaration, 0);
+ this.lastIgnoredToken = -1;
+ }
+ // javadoc
+ enumDeclaration.javadoc = this.javadoc;
+ this.javadoc = null;
+}
protected void consumeEqualityExpression(int op) {
// EqualityExpression ::= EqualityExpression '==' RelationalExpression
// EqualityExpression ::= EqualityExpression '!=' RelationalExpression
@@ -1750,6 +3021,21 @@ protected void consumeEqualityExpression(int op) {
this.expressionStack[this.expressionPtr + 1],
op);
}
+/*
+ * @param op
+ */
+protected void consumeEqualityExpressionWithName(int op) {
+ // EqualityExpression ::= Name '==' RelationalExpression
+ // EqualityExpression ::= Name '!=' RelationalExpression
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ this.expressionPtr--;
+ this.expressionLengthPtr--;
+ this.expressionStack[this.expressionPtr] =
+ new EqualExpression(
+ this.expressionStack[this.expressionPtr + 1],
+ this.expressionStack[this.expressionPtr],
+ op);
+}
protected void consumeExitTryBlock() {
//ExitTryBlock ::= $empty
if(this.currentElement != null) {
@@ -1775,7 +3061,11 @@ protected void consumeExitVariableWithoutInitialization() {
AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
variableDecl.declarationSourceEnd = variableDecl.declarationEnd;
-
+ if(this.currentElement != null && this.currentElement instanceof RecoveredField) {
+ if(this.endStatementPosition > variableDecl.sourceEnd) {
+ this.currentElement.updateSourceEndIfNecessary(this.endStatementPosition);
+ }
+ }
this.recoveryExitFromVariable();
}
protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
@@ -1813,6 +3103,47 @@ protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
pushOnAstStack(ecc);
ecc.sourceEnd = this.endPosition;
}
+protected void consumeExplicitConstructorInvocationWithTypeArguments(int flag, int recFlag) {
+
+ /* flag allows to distinguish 3 cases :
+ (0) :
+ ExplicitConstructorInvocation ::= TypeArguments 'this' '(' ArgumentListopt ')' ';'
+ ExplicitConstructorInvocation ::= TypeArguments 'super' '(' ArgumentListopt ')' ';'
+ (1) :
+ ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
+ ExplicitConstructorInvocation ::= Primary '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
+ (2) :
+ ExplicitConstructorInvocation ::= Name '.' TypeArguments 'super' '(' ArgumentListopt ')' ';'
+ ExplicitConstructorInvocation ::= Name '.' TypeArguments 'this' '(' ArgumentListopt ')' ';'
+ */
+ int startPosition = this.intStack[this.intPtr--];
+ ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag);
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(this.expressionStack, this.expressionPtr + 1, ecc.arguments = new Expression[length], 0, length);
+ }
+ length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, ecc.typeArguments = new TypeReference[length], 0, length);
+ ecc.typeArgumentsSourceStart = this.intStack[intPtr--];
+
+ switch (flag) {
+ case 0 :
+ ecc.sourceStart = startPosition;
+ break;
+ case 1 :
+ this.expressionLengthPtr--;
+ ecc.sourceStart = (ecc.qualification = this.expressionStack[this.expressionPtr--]).sourceStart;
+ break;
+ case 2 :
+ ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
+ break;
+ }
+
+ pushOnAstStack(ecc);
+ ecc.sourceEnd = this.endPosition;
+}
protected void consumeExpressionStatement() {
// ExpressionStatement ::= StatementExpression ';'
this.expressionLengthPtr--;
@@ -1846,15 +3177,15 @@ protected void consumeFieldDeclaration() {
// FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
/*
- astStack :
- expressionStack: Expression Expression ...... Expression
- identifierStack : type identifier identifier ...... identifier
- intStack : typeDim dim dim dim
+ this.astStack :
+ this.expressionStack: Expression Expression ...... Expression
+ this.identifierStack : type identifier identifier ...... identifier
+ this.intStack : typeDim dim dim dim
==>
- astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
- expressionStack :
- identifierStack :
- intStack :
+ this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+ this.expressionStack :
+ this.identifierStack :
+ this.intStack :
*/
int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
@@ -1873,7 +3204,7 @@ protected void consumeFieldDeclaration() {
fieldDeclaration.declarationSourceEnd = endPos;
}
}
- // update the astStack, astPtr and astLengthStack
+ // update the this.astStack, this.astPtr and this.astLengthStack
int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
System.arraycopy(
this.astStack,
@@ -1904,23 +3235,37 @@ protected void consumeForInit() {
// ForInit ::= StatementExpressionList
pushOnAstLengthStack(-1);
}
-protected void consumeFormalParameter() {
+protected void consumeFormalParameter(boolean isVarArgs) {
// FormalParameter ::= Type VariableDeclaratorId ==> false
// FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
/*
- astStack :
- identifierStack : type identifier
- intStack : dim dim
+ this.astStack :
+ this.identifierStack : type identifier
+ this.intStack : dim dim
==>
- astStack : Argument
- identifierStack :
- intStack :
+ this.astStack : Argument
+ this.identifierStack :
+ this.intStack :
*/
this.identifierLengthPtr--;
char[] identifierName = this.identifierStack[this.identifierPtr];
long namePositions = this.identifierPositionStack[this.identifierPtr--];
- TypeReference type = getTypeReference(this.intStack[this.intPtr--] + this.intStack[this.intPtr--]);
+ int extendedDimensions = this.intStack[this.intPtr--];
+ int endOfEllipsis = 0;
+ if (isVarArgs) {
+ endOfEllipsis = this.intStack[this.intPtr--];
+ }
+ int firstDimensions = this.intStack[this.intPtr--];
+ final int typeDimensions = firstDimensions + extendedDimensions;
+ TypeReference type = getTypeReference(typeDimensions);
+ if (isVarArgs) {
+ type = type.copyDims(typeDimensions + 1);
+ if (extendedDimensions == 0) {
+ type.sourceEnd = endOfEllipsis;
+ }
+ type.bits |= ASTNode.IsVarArgs; // set isVarArgs
+ }
int modifierPositions = this.intStack[this.intPtr--];
this.intPtr--;
Argument arg =
@@ -1930,11 +3275,30 @@ protected void consumeFormalParameter() {
type,
this.intStack[this.intPtr + 1] & ~AccDeprecated); // modifiers
arg.declarationSourceStart = modifierPositions;
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ arg.annotations = new Annotation[length],
+ 0,
+ length);
+ }
pushOnAstStack(arg);
- /* if incomplete method header, listLength counter will not have been reset,
+ /* if incomplete method header, this.listLength counter will not have been reset,
indicating that some arguments are available on the stack */
this.listLength++;
+
+ if(isVarArgs) {
+ if (options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfVarargs(arg);
+ } else if (extendedDimensions > 0) {
+ this.problemReporter().illegalExtendedDimensions(arg);
+ }
+ }
}
protected void consumeFormalParameterList() {
// FormalParameterList ::= FormalParameterList ',' FormalParameter
@@ -1944,30 +3308,48 @@ protected void consumeFormalParameterListopt() {
// FormalParameterListopt ::= $empty
pushOnAstLengthStack(0);
}
-protected void consumeImportDeclarations() {
- // ImportDeclarations ::= ImportDeclarations ImportDeclaration
- optimizedConcatNodeLists();
+protected void consumeGenericType() {
+ // nothing to do
+ // Will be consume by a getTypeRefence call
}
-protected void consumeImportDeclarationsopt() {
- // ImportDeclarationsopt ::= ImportDeclarations
- int length;
- if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
- this.astPtr -= length;
- System.arraycopy(
- this.astStack,
- this.astPtr + 1,
- this.compilationUnit.imports = new ImportReference[length],
- 0,
- length);
- }
+protected void consumeGenericTypeArrayType() {
+ // nothing to do
+ // Will be consume by a getTypeRefence call
+}
+protected void consumeGenericTypeNameArrayType() {
+ pushOnGenericsLengthStack(0); // handle type arguments
+}
+protected void consumeImportDeclaration() {
+ // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+ ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+ // flush annotations defined prior to import statements
+ impt.declarationEnd = this.endStatementPosition;
+ impt.declarationSourceEnd =
+ this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
+
+ // recovery
+ if (this.currentElement != null) {
+ this.lastCheckPoint = impt.declarationSourceEnd + 1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true;
+ // used to avoid branching back into the regular automaton
+ }
+}
+protected void consumeImportDeclarations() {
+ // ImportDeclarations ::= ImportDeclarations ImportDeclaration
+ optimizedConcatNodeLists();
}
protected void consumeInsideCastExpression() {
// InsideCastExpression ::= $empty
}
protected void consumeInsideCastExpressionLL1() {
// InsideCastExpressionLL1 ::= $empty
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+}
+protected void consumeInsideCastExpressionWithQualifiedGenerics() {
+ // InsideCastExpressionWithQualifiedGenerics ::= $empty
}
-
protected void consumeInstanceOfExpression(int op) {
// RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
//optimize the push/pop
@@ -1985,6 +3367,28 @@ protected void consumeInstanceOfExpression(int op) {
}
//the scanner is on the next token already....
}
+/**
+ * @param op
+ */
+protected void consumeInstanceOfExpressionWithName(int op) {
+ // RelationalExpression_NotName ::= Name instanceof ReferenceType
+ //optimize the push/pop
+
+ //by construction, no base type may be used in getTypeReference
+ TypeReference reference = getTypeReference(this.intStack[this.intPtr--]);
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ Expression exp;
+ this.expressionStack[this.expressionPtr] = exp =
+ new InstanceOfExpression(
+ this.expressionStack[this.expressionPtr],
+ reference,
+ op);
+ if (exp.sourceEnd == 0) {
+ //array on base type....
+ exp.sourceEnd = this.scanner.startPosition - 1;
+ }
+ //the scanner is on the next token already....
+}
protected void consumeInterfaceDeclaration() {
// see consumeClassDeclaration in case of changes: duplicated code
// InterfaceDeclaration ::= InterfaceHeader InterfaceBody
@@ -2039,6 +3443,9 @@ protected void consumeInterfaceHeaderExtends() {
typeDecl.superInterfaces = new TypeReference[length],
0,
length);
+ for (int i = 0, max = typeDecl.superInterfaces.length; i < max; i++) {
+ typeDecl.superInterfaces[i].bits |= ASTNode.IsSuperType;
+ }
typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
this.listLength = 0; // reset after having read super-interfaces
// recovery
@@ -2046,7 +3453,7 @@ protected void consumeInterfaceHeaderExtends() {
this.lastCheckPoint = typeDecl.bodyStart;
}
}
-protected void consumeInterfaceHeaderName() {
+protected void consumeInterfaceHeaderName1() {
// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
@@ -2075,10 +3482,20 @@ protected void consumeInterfaceHeaderName() {
typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
this.intPtr--; // remove the end position of the class token
typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
- typeDecl.modifiers = this.intStack[this.intPtr--];
+ typeDecl.modifiers = this.intStack[this.intPtr--] | AccInterface;
if (typeDecl.modifiersSourceStart >= 0) {
typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
}
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ typeDecl.annotations = new Annotation[length],
+ 0,
+ length);
+ }
typeDecl.bodyStart = typeDecl.sourceEnd + 1;
pushOnAstStack(typeDecl);
this.listLength = 0; // will be updated when reading super-interfaces
@@ -2103,7 +3520,7 @@ protected void consumeInterfaceMemberDeclarationsopt() {
protected void consumeInterfaceType() {
// InterfaceType ::= ClassOrInterfaceType
pushOnAstStack(getTypeReference(0));
- /* if incomplete type header, listLength counter will not have been reset,
+ /* if incomplete type header, this.listLength counter will not have been reset,
indicating that some interfaces are available on the stack */
this.listLength++;
}
@@ -2111,6 +3528,34 @@ protected void consumeInterfaceTypeList() {
// InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
optimizedConcatNodeLists();
}
+protected void consumeInternalCompilationUnit() {
+ // InternalCompilationUnit ::= PackageDeclaration
+ // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports
+ // InternalCompilationUnit ::= ImportDeclarations ReduceImports
+}
+protected void consumeInternalCompilationUnitWithTypes() {
+ // InternalCompilationUnit ::= PackageDeclaration ImportDeclarations ReduceImports TypeDeclarations
+ // InternalCompilationUnit ::= PackageDeclaration TypeDeclarations
+ // InternalCompilationUnit ::= TypeDeclarations
+ // InternalCompilationUnit ::= ImportDeclarations ReduceImports TypeDeclarations
+ // consume type declarations
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ this.astPtr -= length;
+ System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types = new TypeDeclaration[length], 0, length);
+ }
+}
+protected void consumeInvalidConstructorDeclaration() {
+ // ConstructorDeclaration ::= ConstructorHeader ';'
+ // now we know that the top of stack is a constructorDeclaration
+ ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
+
+ cd.bodyEnd = this.endPosition; // position just before the trailing semi-colon
+ cd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+ // report the problem and continue the parsing - narrowing the problem onto the method
+
+ cd.modifiers |= AccSemicolonBody; // remember semi-colon body
+}
protected void consumeLeftParen() {
// PushLPAREN ::= '('
pushOnIntStack(this.lParenPos);
@@ -2119,20 +3564,20 @@ protected void consumeLocalVariableDeclaration() {
// LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';'
/*
- astStack :
- expressionStack: Expression Expression ...... Expression
- identifierStack : type identifier identifier ...... identifier
- intStack : typeDim dim dim dim
+ this.astStack :
+ this.expressionStack: Expression Expression ...... Expression
+ this.identifierStack : type identifier identifier ...... identifier
+ this.intStack : typeDim dim dim dim
==>
- astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
- expressionStack :
- identifierStack :
- intStack :
+ this.astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+ this.expressionStack :
+ this.identifierStack :
+ this.intStack :
*/
int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
- // update the astStack, astPtr and astLengthStack
+ // update the this.astStack, this.astPtr and this.astLengthStack
int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
System.arraycopy(
this.astStack,
@@ -2159,6 +3604,70 @@ protected void consumeLocalVariableDeclarationStatement() {
}
}
+protected void consumeMarkerAnnotation() {
+ // MarkerAnnotation ::= '@' Name
+ MarkerAnnotation markerAnnotation = null;
+ int length = this.identifierLengthStack[this.identifierLengthPtr--];
+ TypeReference typeReference;
+ if (length == 1) {
+ typeReference = new SingleTypeReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ } else {
+ char[][] tokens = new char[length][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ this.identifierPositionStack,
+ this.identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ typeReference = new QualifiedTypeReference(tokens, positions);
+ }
+ markerAnnotation = new MarkerAnnotation(typeReference, this.intStack[this.intPtr--]);
+ int sourceStart = markerAnnotation.sourceStart;
+ if (this.modifiersSourceStart < 0) {
+ this.modifiersSourceStart = sourceStart;
+ } else if (this.modifiersSourceStart > sourceStart) {
+ this.modifiersSourceStart = sourceStart;
+ }
+ markerAnnotation.declarationSourceEnd = markerAnnotation.sourceEnd;
+ pushOnExpressionStack(markerAnnotation);
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfAnnotation(markerAnnotation);
+ }
+}
+protected void consumeMemberValueArrayInitializer() {
+ // MemberValueArrayInitializer ::= '{' MemberValues ',' '}'
+ // MemberValueArrayInitializer ::= '{' MemberValues '}'
+ arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
+}
+protected void consumeMemberValueAsName() {
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+}
+protected void consumeMemberValuePair() {
+ // MemberValuePair ::= SimpleName '=' MemberValue
+ char[] simpleName = this.identifierStack[this.identifierPtr];
+ long position = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+ int end = (int) position;
+ int start = (int) (position >>> 32);
+ Expression value = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+ MemberValuePair memberValuePair = new MemberValuePair(simpleName, start, end, value);
+ pushOnAstStack(memberValuePair);
+}
+protected void consumeMemberValuePairs() {
+ // MemberValuePairs ::= MemberValuePairs ',' MemberValuePair
+ concatNodeLists();
+}
+protected void consumeMemberValues() {
+ // MemberValues ::= MemberValues ',' MemberValue
+ concatExpressionLists();
+}
protected void consumeMethodBody() {
// MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
this.nestedMethod[this.nestedType] --;
@@ -2168,13 +3677,13 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
// AbstractMethodDeclaration ::= MethodHeader ';'
/*
- astStack : modifiers arguments throws statements
- identifierStack : type name
- intStack : dim dim dim
+ this.astStack : modifiers arguments throws statements
+ this.identifierStack : type name
+ this.intStack : dim dim dim
==>
- astStack : MethodDeclaration
- identifierStack :
- intStack :
+ this.astStack : MethodDeclaration
+ this.identifierStack :
+ this.intStack :
*/
int length;
@@ -2215,13 +3724,17 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
}
}
}
- // store the endPosition (position just before the '}') in case there is
+ // store the this.endPosition (position just before the '}') in case there is
// a trailing comment behind the end of the method
md.bodyEnd = this.endPosition;
md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
}
protected void consumeMethodHeader() {
// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ // AnnotationMethodHeader ::= AnnotationMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+ // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims AnnotationMethodHeaderDefaultValueopt
+ // RecoveryMethodHeader ::= RecoveryMethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClause
+
// retrieve end position of method declarator
AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
@@ -2230,7 +3743,13 @@ protected void consumeMethodHeader() {
}
// recovery
if (this.currentElement != null){
- if (this.currentToken == TokenNameSEMICOLON){
+// if(method.isAnnotationMethod()) {
+// method.modifiers |= AccSemicolonBody;
+// method.declarationSourceEnd = this.scanner.currentPosition-1;
+// method.bodyEnd = this.scanner.currentPosition-1;
+// this.currentElement = this.currentElement.parent;
+// } else
+ if (this.currentToken == TokenNameSEMICOLON /*&& !method.isAnnotationMethod()*/){
method.modifiers |= AccSemicolonBody;
method.declarationSourceEnd = this.scanner.currentPosition-1;
method.bodyEnd = this.scanner.currentPosition-1;
@@ -2241,11 +3760,36 @@ protected void consumeMethodHeader() {
this.restartRecovery = true; // used to avoid branching back into the regular automaton
}
}
+protected void consumeMethodHeaderDefaultValue() {
+ // MethodHeaderDefaultValue ::= DefaultValue
+ MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
+
+
+ int length = this.expressionLengthStack[this.expressionLengthPtr--];
+ if (length == 1) {
+ intPtr--; // we get rid of the position of the default keyword
+ intPtr--; // we get rid of the position of the default keyword
+ if(md.isAnnotationMethod()) {
+ ((AnnotationMethodDeclaration)md).defaultValue = this.expressionStack[this.expressionPtr];
+ md.modifiers |= AccAnnotationDefault;
+ }
+ this.expressionPtr--;
+ }
+
+ if(this.currentElement != null) {
+ if(md.isAnnotationMethod()) {
+ this.currentElement.updateSourceEndIfNecessary(((AnnotationMethodDeclaration)md).defaultValue.sourceEnd);
+ }
+ }
+}
protected void consumeMethodHeaderExtendedDims() {
// MethodHeaderExtendedDims ::= Dimsopt
// now we update the returnType of the method
MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
int extendedDims = this.intStack[this.intPtr--];
+ if(md.isAnnotationMethod()) {
+ ((AnnotationMethodDeclaration)md).extendedDimensions = extendedDims;
+ }
if (extendedDims != 0) {
TypeReference returnType = md.returnType;
md.sourceEnd = this.endPosition;
@@ -2271,9 +3815,72 @@ protected void consumeMethodHeaderExtendedDims() {
}
}
}
-protected void consumeMethodHeaderName() {
+protected void consumeMethodHeaderName(boolean isAnnotationMethod) {
// MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
- MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+ // AnnotationMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ // RecoveryMethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ MethodDeclaration md = null;
+ if(isAnnotationMethod) {
+ md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ md = new MethodDeclaration(this.compilationUnit.compilationResult);
+ }
+
+ //name
+ md.selector = this.identifierStack[this.identifierPtr];
+ long selectorSource = this.identifierPositionStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(this.intStack[this.intPtr--]);
+ //modifiers
+ md.declarationSourceStart = this.intStack[this.intPtr--];
+ md.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ md.annotations = new Annotation[length],
+ 0,
+ length);
+ }
+ // javadoc
+ md.javadoc = this.javadoc;
+ this.javadoc = null;
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSource >>> 32);
+ pushOnAstStack(md);
+ md.sourceEnd = this.lParenPos;
+ md.bodyStart = this.lParenPos+1;
+ this.listLength = 0; // initialize this.listLength before reading parameters/throws
+
+ // recovery
+ if (this.currentElement != null){
+ if (this.currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || (this.scanner.getLineNumber(md.returnType.sourceStart)
+ == this.scanner.getLineNumber(md.sourceStart))){
+ this.lastCheckPoint = md.bodyStart;
+ this.currentElement = this.currentElement.add(md, 0);
+ this.lastIgnoredToken = -1;
+ } else {
+ this.lastCheckPoint = md.sourceStart;
+ this.restartRecovery = true;
+ }
+ }
+}
+protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
+ // MethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+ // AnnotationMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+ // RecoveryMethodHeaderName ::= Modifiersopt TypeParameters Type 'Identifier' '('
+ MethodDeclaration md = null;
+ if(isAnnotationMethod) {
+ md = new AnnotationMethodDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ md = new MethodDeclaration(this.compilationUnit.compilationResult);
+ }
//name
md.selector = this.identifierStack[this.identifierPtr];
@@ -2281,9 +3888,24 @@ protected void consumeMethodHeaderName() {
this.identifierLengthPtr--;
//type
md.returnType = getTypeReference(this.intStack[this.intPtr--]);
+
+ // consume type parameters
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, md.typeParameters = new TypeParameter[length], 0, length);
+
//modifiers
md.declarationSourceStart = this.intStack[this.intPtr--];
md.modifiers = this.intStack[this.intPtr--];
+ // consume annotations
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ md.annotations = new Annotation[length],
+ 0,
+ length);
+ }
// javadoc
md.javadoc = this.javadoc;
this.javadoc = null;
@@ -2293,7 +3915,7 @@ protected void consumeMethodHeaderName() {
pushOnAstStack(md);
md.sourceEnd = this.lParenPos;
md.bodyStart = this.lParenPos+1;
- this.listLength = 0; // initialize listLength before reading parameters/throws
+ this.listLength = 0; // initialize this.listLength before reading parameters/throws
// recovery
if (this.currentElement != null){
@@ -2310,7 +3932,7 @@ protected void consumeMethodHeaderName() {
}
}
}
-protected void consumeMethodHeaderParameters() {
+protected void consumeMethodHeaderRightParen() {
// MethodHeaderParameters ::= FormalParameterListopt ')'
int length = this.astLengthStack[this.astLengthPtr--];
this.astPtr -= length;
@@ -2326,7 +3948,7 @@ protected void consumeMethodHeaderParameters() {
length);
}
md.bodyStart = this.rParenPos+1;
- this.listLength = 0; // reset listLength after having read all parameters
+ this.listLength = 0; // reset this.listLength after having read all parameters
// recovery
if (this.currentElement != null){
this.lastCheckPoint = md.bodyStart;
@@ -2356,11 +3978,11 @@ protected void consumeMethodHeaderThrowsClause() {
length);
md.sourceEnd = md.thrownExceptions[length-1].sourceEnd;
md.bodyStart = md.thrownExceptions[length-1].sourceEnd + 1;
- this.listLength = 0; // reset listLength after having read all thrown exceptions
+ this.listLength = 0; // reset this.listLength after having read all thrown exceptions
// recovery
if (this.currentElement != null){
this.lastCheckPoint = md.bodyStart;
- }
+ }
}
protected void consumeMethodInvocationName() {
// MethodInvocation ::= Name '(' ArgumentListopt ')'
@@ -2382,6 +4004,28 @@ protected void consumeMethodInvocationName() {
}
pushOnExpressionStack(m);
}
+protected void consumeMethodInvocationNameWithTypeArguments() {
+ // MethodInvocation ::= Name '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+ // when the name is only an identifier...we have a message send to "this" (implicit)
+
+ MessageSend m = newMessageSendWithTypeArguments();
+ m.sourceEnd = this.rParenPos;
+ m.sourceStart =
+ (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
+ m.selector = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ // handle type arguments
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+ intPtr--;
+
+ m.receiver = getUnspecifiedReference();
+ m.sourceStart = m.receiver.sourceStart;
+ pushOnExpressionStack(m);
+}
protected void consumeMethodInvocationPrimary() {
//optimize the push/pop
//MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
@@ -2396,6 +4040,27 @@ protected void consumeMethodInvocationPrimary() {
m.sourceEnd = this.rParenPos;
this.expressionStack[this.expressionPtr] = m;
}
+protected void consumeMethodInvocationPrimaryWithTypeArguments() {
+ //optimize the push/pop
+ //MethodInvocation ::= Primary '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+ MessageSend m = newMessageSendWithTypeArguments();
+ m.sourceStart =
+ (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
+ m.selector = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ // handle type arguments
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+ intPtr--;
+
+ m.receiver = this.expressionStack[this.expressionPtr];
+ m.sourceStart = m.receiver.sourceStart;
+ m.sourceEnd = this.rParenPos;
+ this.expressionStack[this.expressionPtr] = m;
+}
protected void consumeMethodInvocationSuper() {
// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
@@ -2408,6 +4073,25 @@ protected void consumeMethodInvocationSuper() {
m.receiver = new SuperReference(m.sourceStart, this.endPosition);
pushOnExpressionStack(m);
}
+protected void consumeMethodInvocationSuperWithTypeArguments() {
+ // MethodInvocation ::= 'super' '.' TypeArguments 'Identifier' '(' ArgumentListopt ')'
+
+ MessageSend m = newMessageSendWithTypeArguments();
+ m.sourceStart = this.intStack[this.intPtr--];
+ m.sourceEnd = this.rParenPos;
+ m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
+ m.selector = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+
+ // handle type arguments
+ int length = this.genericsLengthStack[this.genericsLengthPtr--];
+ this.genericsPtr -= length;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, m.typeArguments = new TypeReference[length], 0, length);
+ intPtr--;
+
+ m.receiver = new SuperReference(m.sourceStart, this.endPosition);
+ pushOnExpressionStack(m);
+}
protected void consumeModifiers() {
int savedModifiersSourceStart = this.modifiersSourceStart;
checkComment(); // might update modifiers with AccDeprecated
@@ -2418,6 +4102,13 @@ protected void consumeModifiers() {
pushOnIntStack(this.modifiersSourceStart);
resetModifiers();
}
+protected void consumeModifiers2() {
+ this.expressionLengthStack[this.expressionLengthPtr - 1] += this.expressionLengthStack[this.expressionLengthPtr--];
+}
+protected void consumeNameArrayType() {
+ pushOnGenericsLengthStack(0); // handle type arguments
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+}
protected void consumeNestedMethod() {
// NestedMethod ::= $empty
jumpOverMethodBody();
@@ -2442,6 +4133,50 @@ protected void consumeNestedType() {
this.nestedMethod[this.nestedType] = 0;
this.variablesCounter[this.nestedType] = 0;
}
+protected void consumeNormalAnnotation() {
+ // NormalAnnotation ::= '@' Name '(' MemberValuePairsopt ')'
+ NormalAnnotation normalAnnotation = null;
+ int length = this.identifierLengthStack[this.identifierLengthPtr--];
+ TypeReference typeReference;
+ if (length == 1) {
+ typeReference = new SingleTypeReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ } else {
+ char[][] tokens = new char[length][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ this.identifierPositionStack,
+ this.identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ typeReference = new QualifiedTypeReference(tokens, positions);
+ }
+ normalAnnotation = new NormalAnnotation(typeReference, this.intStack[this.intPtr--]);
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.astStack,
+ (this.astPtr -= length) + 1,
+ normalAnnotation.memberValuePairs = new MemberValuePair[length],
+ 0,
+ length);
+ }
+ int sourceStart = normalAnnotation.sourceStart;
+ if (this.modifiersSourceStart < 0) {
+ this.modifiersSourceStart = sourceStart;
+ } else if (this.modifiersSourceStart > sourceStart) {
+ this.modifiersSourceStart = sourceStart;
+ }
+ normalAnnotation.declarationSourceEnd = this.rParenPos;
+ pushOnExpressionStack(normalAnnotation);
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfAnnotation(normalAnnotation);
+ }
+}
protected void consumeOneDimLoop() {
// OneDimLoop ::= '[' ']'
this.dimensions++;
@@ -2450,6 +4185,19 @@ protected void consumeOnlySynchronized() {
// OnlySynchronized ::= 'synchronized'
pushOnIntStack(this.synchronizedBlockSourceStart);
resetModifiers();
+ this.expressionLengthPtr--;
+}
+protected void consumeOnlyTypeArguments() {
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ int length = this.genericsLengthStack[this.genericsLengthPtr];
+ this.problemReporter().invalidUsageOfTypeArguments(
+ (TypeReference)this.genericsStack[this.genericsPtr - length + 1],
+ (TypeReference)this.genericsStack[this.genericsPtr]);
+ }
+}
+protected void consumeOnlyTypeArgumentsForCastExpression() {
+ // OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments
}
protected void consumeOpenBlock() {
// OpenBlock ::= $empty
@@ -2491,9 +4239,10 @@ protected void consumePackageDeclarationName() {
this.identifierPtr--,
positions,
0,
- length);
- this.compilationUnit.currentPackage =
- impt = new ImportReference(tokens, positions, true, AccDefault);
+ length);
+
+ impt = new ImportReference(tokens, positions, true, AccDefault);
+ this.compilationUnit.currentPackage = impt;
if (this.currentToken == TokenNameSEMICOLON){
impt.declarationSourceEnd = this.scanner.currentPosition - 1;
@@ -2501,7 +4250,7 @@ protected void consumePackageDeclarationName() {
impt.declarationSourceEnd = impt.sourceEnd;
}
impt.declarationEnd = impt.declarationSourceEnd;
- //endPosition is just before the ;
+ //this.endPosition is just before the ;
impt.declarationSourceStart = this.intStack[this.intPtr--];
// recovery
@@ -2510,67 +4259,172 @@ protected void consumePackageDeclarationName() {
this.restartRecovery = true; // used to avoid branching back into the regular automaton
}
}
-protected void consumePostfixExpression() {
- // PostfixExpression ::= Name
- pushOnExpressionStack(getUnspecifiedReferenceOptimized());
-}
-protected void consumePrimaryNoNewArray() {
- // PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN
- final Expression parenthesizedExpression = this.expressionStack[this.expressionPtr];
- updateSourcePosition(parenthesizedExpression);
- int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
- parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
- parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
-}
-protected void consumePrimaryNoNewArrayArrayType() {
- // PrimaryNoNewArray ::= ArrayType '.' 'class'
- this.intPtr--;
- pushOnExpressionStack(
- new ClassLiteralAccess(this.intStack[this.intPtr--],
- getTypeReference(this.intStack[this.intPtr--])));
-}
-protected void consumePrimaryNoNewArrayName() {
- // PrimaryNoNewArray ::= Name '.' 'class'
- this.intPtr--;
- pushOnExpressionStack(
- new ClassLiteralAccess(this.intStack[this.intPtr--],
- getTypeReference(0)));
-}
-protected void consumePrimaryNoNewArrayNameSuper() {
- // PrimaryNoNewArray ::= Name '.' 'super'
- pushOnExpressionStack(
- new QualifiedSuperReference(
- getTypeReference(0),
- this.intStack[this.intPtr--],
- this.endPosition));
-}
-protected void consumePrimaryNoNewArrayNameThis() {
- // PrimaryNoNewArray ::= Name '.' 'this'
- pushOnExpressionStack(
+protected void consumePackageDeclarationNameWithModifiers() {
+ // PackageDeclarationName ::= Modifiers 'package' Name
+ /* build an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ ImportReference impt;
+ int length;
+ char[][] tokens =
+ new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, ++this.identifierPtr, tokens, 0, length);
+ System.arraycopy(
+ this.identifierPositionStack,
+ this.identifierPtr--,
+ positions,
+ 0,
+ length);
+
+ int packageModifiersSourceStart = this.intStack[this.intPtr--]; // we don't need the modifiers start
+ int packageModifiers = this.intStack[this.intPtr--];
+
+ impt = new ImportReference(tokens, positions, true, packageModifiers);
+ this.compilationUnit.currentPackage = impt;
+ // consume annotations
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.expressionStack,
+ (this.expressionPtr -= length) + 1,
+ impt.annotations = new Annotation[length],
+ 0,
+ length);
+ impt.declarationSourceStart = packageModifiersSourceStart;
+ intPtr--; // we don't need the position of the 'package keyword
+ } else {
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+ }
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+}
+protected void consumePostfixExpression() {
+ // PostfixExpression ::= Name
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+}
+protected void consumePrimaryNoNewArray() {
+ // PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN
+ final Expression parenthesizedExpression = this.expressionStack[this.expressionPtr];
+ updateSourcePosition(parenthesizedExpression);
+ int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+ parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
+ parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
+}
+protected void consumePrimaryNoNewArrayArrayType() {
+ // PrimaryNoNewArray ::= Name Dims '.' 'class'
+ this.intPtr--; // remove the class start position
+
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+
+ pushOnExpressionStack(
+ new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(this.intStack[this.intPtr--])));
+}
+protected void consumePrimaryNoNewArrayName() {
+ // PrimaryNoNewArray ::= Name '.' 'class'
+ this.intPtr--; // remove the class start position
+
+ // handle type arguments
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+ TypeReference typeReference = getTypeReference(0);
+
+ pushOnExpressionStack(
+ new ClassLiteralAccess(this.intStack[this.intPtr--], typeReference));
+}
+protected void consumePrimaryNoNewArrayNameSuper() {
+ // PrimaryNoNewArray ::= Name '.' 'super'
+ // handle type arguments
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0);
+ TypeReference typeReference = getTypeReference(0);
+
+ pushOnExpressionStack(
+ new QualifiedSuperReference(
+ typeReference,
+ this.intStack[this.intPtr--],
+ this.endPosition));
+}
+protected void consumePrimaryNoNewArrayNameThis() {
+ // PrimaryNoNewArray ::= Name '.' 'this'
+ // handle type arguments
+ pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
+ pushOnGenericsLengthStack(0); // handle type arguments
+
+ TypeReference typeReference = getTypeReference(0);
+
+ pushOnExpressionStack(
new QualifiedThisReference(
- getTypeReference(0),
+ typeReference,
this.intStack[this.intPtr--],
this.endPosition));
}
+protected void consumePrimaryNoNewArrayPrimitiveArrayType() {
+ // PrimaryNoNewArray ::= PrimitiveType Dims '.' 'class'
+ this.intPtr--; // remove the class start position
+ pushOnExpressionStack(
+ new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(this.intStack[this.intPtr--])));
+}
protected void consumePrimaryNoNewArrayPrimitiveType() {
// PrimaryNoNewArray ::= PrimitiveType '.' 'class'
- this.intPtr--;
+ this.intPtr--; // remove the class start position
pushOnExpressionStack(
- new ClassLiteralAccess(this.intStack[this.intPtr--],
- getTypeReference(0)));
+ new ClassLiteralAccess(this.intStack[this.intPtr--], getTypeReference(0)));
}
protected void consumePrimaryNoNewArrayThis() {
// PrimaryNoNewArray ::= 'this'
pushOnExpressionStack(new ThisReference(this.intStack[this.intPtr--], this.endPosition));
}
+protected void consumePrimaryNoNewArrayWithName() {
+ // PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+ final Expression parenthesizedExpression = this.expressionStack[this.expressionPtr];
+ updateSourcePosition(parenthesizedExpression);
+ int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+ parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
+ parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
+}
+protected void consumePrimitiveArrayType() {
+ // nothing to do
+ // Will be consume by a getTypeRefence call
+}
protected void consumePrimitiveType() {
// Type ::= PrimitiveType
pushOnIntStack(0);
}
+protected void consumePushLeftBrace() {
+ pushOnIntStack(this.endPosition); // modifiers
+}
+protected void consumePushRealModifiers() {
+ checkComment(); // might update modifiers with AccDeprecated
+ pushOnIntStack(this.modifiers); // modifiers
+ pushOnIntStack(this.modifiersSourceStart);
+ resetModifiers();
+}
protected void consumePushModifiers() {
pushOnIntStack(this.modifiers); // modifiers
pushOnIntStack(this.modifiersSourceStart);
resetModifiers();
+ pushOnExpressionStackLengthStack(0);
+}
+protected void consumePushModifiersForHeader() {
+ checkComment(); // might update modifiers with AccDeprecated
+ pushOnIntStack(this.modifiers); // modifiers
+ pushOnIntStack(this.modifiersSourceStart);
+ resetModifiers();
+ pushOnExpressionStackLengthStack(0);
}
protected void consumePushPosition() {
// for source managment purpose
@@ -2584,9 +4438,56 @@ protected void consumeQualifiedName() {
this.identifierLengthStack[--this.identifierLengthPtr]++;
}
+protected void consumeRecoveryMethodHeaderName() {
+ // this method is call only inside recovery
+ boolean isAnnotationMethod = false;
+ if(this.currentElement instanceof RecoveredType) {
+ isAnnotationMethod = (((RecoveredType)this.currentElement).typeDeclaration.modifiers & AccAnnotation) != 0;
+ } else {
+ RecoveredType recoveredType = this.currentElement.enclosingType();
+ if(recoveredType != null) {
+ isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & AccAnnotation) != 0;
+ }
+ }
+ this.consumeMethodHeaderName(isAnnotationMethod);
+}
+protected void consumeRecoveryMethodHeaderNameWithTypeParameters() {
+ // this method is call only inside recovery
+ boolean isAnnotationMethod = false;
+ if(this.currentElement instanceof RecoveredType) {
+ isAnnotationMethod = (((RecoveredType)this.currentElement).typeDeclaration.modifiers & AccAnnotation) != 0;
+ } else {
+ RecoveredType recoveredType = this.currentElement.enclosingType();
+ if(recoveredType != null) {
+ isAnnotationMethod = (recoveredType.typeDeclaration.modifiers & AccAnnotation) != 0;
+ }
+ }
+ this.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
+}
+protected void consumeReduceImports() {
+ // Consume imports
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ this.astPtr -= length;
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + 1,
+ this.compilationUnit.imports = new ImportReference[length],
+ 0,
+ length);
+ }
+}
protected void consumeReferenceType() {
- // ReferenceType ::= ClassOrInterfaceType
- pushOnIntStack(0);
+ pushOnIntStack(0); // handle array type
+}
+protected void consumeReferenceType1() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
+}
+protected void consumeReferenceType2() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
+}
+protected void consumeReferenceType3() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
}
protected void consumeRestoreDiet() {
// RestoreDiet ::= $empty
@@ -2598,895 +4499,1629 @@ protected void consumeRightParen() {
}
// This method is part of an automatic generation : do NOT edit-modify
protected void consumeRule(int act) {
- switch ( act ) {
- case 26 : // System.out.println("Type ::= PrimitiveType"); //$NON-NLS-1$
- consumePrimitiveType();
- break ;
-
- case 40 : // System.out.println("ReferenceType ::= ClassOrInterfaceType"); //$NON-NLS-1$
- consumeReferenceType();
- break ;
-
- case 49 : // System.out.println("QualifiedName ::= Name DOT SimpleName"); //$NON-NLS-1$
- consumeQualifiedName();
- break ;
-
- case 50 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt..."); //$NON-NLS-1$
- consumeCompilationUnit();
- break ;
-
- case 51 : // System.out.println("EnterCompilationUnit ::="); //$NON-NLS-1$
- consumeEnterCompilationUnit();
- break ;
-
- case 64 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE"); //$NON-NLS-1$
- consumeCatchHeader();
- break ;
-
- case 66 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration"); //$NON-NLS-1$
- consumeImportDeclarations();
- break ;
-
- case 68 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); //$NON-NLS-1$
- consumeTypeDeclarations();
- break ;
-
- case 69 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); //$NON-NLS-1$
- consumePackageDeclaration();
- break ;
-
- case 70 : // System.out.println("PackageDeclarationName ::= package Name"); //$NON-NLS-1$
- consumePackageDeclarationName();
- break ;
-
- case 73 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName..."); //$NON-NLS-1$
- consumeSingleTypeImportDeclaration();
- break ;
-
- case 74 : // System.out.println("SingleTypeImportDeclarationName ::= import Name"); //$NON-NLS-1$
- consumeSingleTypeImportDeclarationName();
- break ;
-
- case 75 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName"); //$NON-NLS-1$
- consumeTypeImportOnDemandDeclaration();
- break ;
-
- case 76 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY"); //$NON-NLS-1$
- consumeTypeImportOnDemandDeclarationName();
- break ;
-
- case 79 : // System.out.println("TypeDeclaration ::= SEMICOLON"); //$NON-NLS-1$
- consumeEmptyTypeDeclaration();
- break ;
-
- case 93 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); //$NON-NLS-1$
- consumeClassDeclaration();
- break ;
-
- case 94 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); //$NON-NLS-1$
- consumeClassHeader();
- break ;
-
- case 95 : // System.out.println("ClassHeaderName ::= Modifiersopt class Identifier"); //$NON-NLS-1$
- consumeClassHeaderName();
- break ;
-
- case 96 : // System.out.println("ClassHeaderExtends ::= extends ClassType"); //$NON-NLS-1$
- consumeClassHeaderExtends();
- break ;
-
- case 97 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); //$NON-NLS-1$
- consumeClassHeaderImplements();
- break ;
-
- case 99 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType"); //$NON-NLS-1$
- consumeInterfaceTypeList();
- break ;
-
- case 100 : // System.out.println("InterfaceType ::= ClassOrInterfaceType"); //$NON-NLS-1$
- consumeInterfaceType();
- break ;
-
- case 103 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration"); //$NON-NLS-1$
- consumeClassBodyDeclarations();
- break ;
-
- case 107 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block"); //$NON-NLS-1$
- consumeClassBodyDeclaration();
- break ;
-
- case 108 : // System.out.println("Diet ::="); //$NON-NLS-1$
- consumeDiet();
- break ;
+ switch ( act ) {
+ case 29 : if (DEBUG) { System.out.println("Type ::= PrimitiveType"); } //$NON-NLS-1$
+ consumePrimitiveType();
+ break;
+
+ case 43 : if (DEBUG) { System.out.println("ReferenceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$
+ consumeReferenceType();
+ break;
+
+ case 47 : if (DEBUG) { System.out.println("ClassOrInterface ::= Name"); } //$NON-NLS-1$
+ consumeClassOrInterfaceName();
+ break;
+
+ case 48 : if (DEBUG) { System.out.println("ClassOrInterface ::= GenericType DOT Name"); } //$NON-NLS-1$
+ consumeClassOrInterface();
+ break;
+
+ case 49 : if (DEBUG) { System.out.println("GenericType ::= ClassOrInterface TypeArguments"); } //$NON-NLS-1$
+ consumeGenericType();
+ break;
+
+ case 50 : if (DEBUG) { System.out.println("ArrayTypeWithTypeArgumentsName ::= GenericType DOT Name"); } //$NON-NLS-1$
+ consumeArrayTypeWithTypeArgumentsName();
+ break;
+
+ case 51 : if (DEBUG) { System.out.println("ArrayType ::= PrimitiveType Dims"); } //$NON-NLS-1$
+ consumePrimitiveArrayType();
+ break;
+
+ case 52 : if (DEBUG) { System.out.println("ArrayType ::= Name Dims"); } //$NON-NLS-1$
+ consumeNameArrayType();
+ break;
+
+ case 53 : if (DEBUG) { System.out.println("ArrayType ::= ArrayTypeWithTypeArgumentsName Dims"); } //$NON-NLS-1$
+ consumeGenericTypeNameArrayType();
+ break;
+
+ case 54 : if (DEBUG) { System.out.println("ArrayType ::= GenericType Dims"); } //$NON-NLS-1$
+ consumeGenericTypeArrayType();
+ break;
+
+ case 59 : if (DEBUG) { System.out.println("QualifiedName ::= Name DOT SimpleName"); } //$NON-NLS-1$
+ consumeQualifiedName();
+ break;
+
+ case 60 : if (DEBUG) { System.out.println("CompilationUnit ::= EnterCompilationUnit..."); } //$NON-NLS-1$
+ consumeCompilationUnit();
+ break;
+
+ case 61 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration"); } //$NON-NLS-1$
+ consumeInternalCompilationUnit();
+ break;
+
+ case 62 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$
+ consumeInternalCompilationUnit();
+ break;
+
+ case 63 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$
+ consumeInternalCompilationUnitWithTypes();
+ break;
+
+ case 64 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= PackageDeclaration..."); } //$NON-NLS-1$
+ consumeInternalCompilationUnitWithTypes();
+ break;
+
+ case 65 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); } //$NON-NLS-1$
+ consumeInternalCompilationUnit();
+ break;
+
+ case 66 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= TypeDeclarations"); } //$NON-NLS-1$
+ consumeInternalCompilationUnitWithTypes();
+ break;
+
+ case 67 : if (DEBUG) { System.out.println("InternalCompilationUnit ::= ImportDeclarations..."); } //$NON-NLS-1$
+ consumeInternalCompilationUnitWithTypes();
+ break;
+
+ case 68 : if (DEBUG) { System.out.println("InternalCompilationUnit ::="); } //$NON-NLS-1$
+ consumeEmptyInternalCompilationUnit();
+ break;
+
+ case 69 : if (DEBUG) { System.out.println("ReduceImports ::="); } //$NON-NLS-1$
+ consumeReduceImports();
+ break;
+
+ case 70 : if (DEBUG) { System.out.println("EnterCompilationUnit ::="); } //$NON-NLS-1$
+ consumeEnterCompilationUnit();
+ break;
+
+ case 86 : if (DEBUG) { System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN..."); } //$NON-NLS-1$
+ consumeCatchHeader();
+ break;
+
+ case 88 : if (DEBUG) { System.out.println("ImportDeclarations ::= ImportDeclarations..."); } //$NON-NLS-1$
+ consumeImportDeclarations();
+ break;
+
+ case 90 : if (DEBUG) { System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration"); } //$NON-NLS-1$
+ consumeTypeDeclarations();
+ break;
+
+ case 91 : if (DEBUG) { System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON"); } //$NON-NLS-1$
+ consumePackageDeclaration();
+ break;
+
+ case 92 : if (DEBUG) { System.out.println("PackageDeclarationName ::= Modifiers package..."); } //$NON-NLS-1$
+ consumePackageDeclarationNameWithModifiers();
+ break;
+
+ case 93 : if (DEBUG) { System.out.println("PackageDeclarationName ::= package Name"); } //$NON-NLS-1$
+ consumePackageDeclarationName();
+ break;
+
+ case 98 : if (DEBUG) { System.out.println("SingleTypeImportDeclaration ::=..."); } //$NON-NLS-1$
+ consumeImportDeclaration();
+ break;
+
+ case 99 : if (DEBUG) { System.out.println("SingleTypeImportDeclarationName ::= import Name"); } //$NON-NLS-1$
+ consumeSingleTypeImportDeclarationName();
+ break;
+
+ case 100 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$
+ consumeImportDeclaration();
+ break;
+
+ case 101 : if (DEBUG) { System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT..."); } //$NON-NLS-1$
+ consumeTypeImportOnDemandDeclarationName();
+ break;
+
+ case 104 : if (DEBUG) { System.out.println("TypeDeclaration ::= SEMICOLON"); } //$NON-NLS-1$
+ consumeEmptyTypeDeclaration();
+ break;
+
+ case 108 : if (DEBUG) { System.out.println("Modifiers ::= Modifiers Modifier"); } //$NON-NLS-1$
+ consumeModifiers2();
+ break;
+
+ case 120 : if (DEBUG) { System.out.println("Modifier ::= Annotation"); } //$NON-NLS-1$
+ consumeAnnotationAsModifier();
+ break;
+
+ case 121 : if (DEBUG) { System.out.println("ClassDeclaration ::= ClassHeader ClassBody"); } //$NON-NLS-1$
+ consumeClassDeclaration();
+ break;
+
+ case 122 : if (DEBUG) { System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt..."); } //$NON-NLS-1$
+ consumeClassHeader();
+ break;
+
+ case 123 : if (DEBUG) { System.out.println("ClassHeaderName ::= ClassHeaderName1 TypeParameters"); } //$NON-NLS-1$
+ consumeTypeHeaderNameWithTypeParameters();
+ break;
+
+ case 125 : if (DEBUG) { System.out.println("ClassHeaderName1 ::= Modifiersopt class Identifier"); } //$NON-NLS-1$
+ consumeClassHeaderName1();
+ break;
+
+ case 126 : if (DEBUG) { System.out.println("ClassHeaderExtends ::= extends ClassType"); } //$NON-NLS-1$
+ consumeClassHeaderExtends();
+ break;
+
+ case 127 : if (DEBUG) { System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList"); } //$NON-NLS-1$
+ consumeClassHeaderImplements();
+ break;
+
+ case 129 : if (DEBUG) { System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA..."); } //$NON-NLS-1$
+ consumeInterfaceTypeList();
+ break;
+
+ case 130 : if (DEBUG) { System.out.println("InterfaceType ::= ClassOrInterfaceType"); } //$NON-NLS-1$
+ consumeInterfaceType();
+ break;
+
+ case 133 : if (DEBUG) { System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations..."); } //$NON-NLS-1$
+ consumeClassBodyDeclarations();
+ break;
+
+ case 137 : if (DEBUG) { System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block"); } //$NON-NLS-1$
+ consumeClassBodyDeclaration();
+ break;
+
+ case 138 : if (DEBUG) { System.out.println("Diet ::="); } //$NON-NLS-1$
+ consumeDiet();
+ break;
- case 109 : // System.out.println("Initializer ::= Diet NestedMethod Block"); //$NON-NLS-1$
- consumeClassBodyDeclaration();
- break ;
-
- case 116 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON"); //$NON-NLS-1$
- consumeEmptyClassMemberDeclaration();
- break ;
+ case 139 : if (DEBUG) { System.out.println("Initializer ::= Diet NestedMethod Block"); } //$NON-NLS-1$
+ consumeClassBodyDeclaration();
+ break;
+
+ case 146 : if (DEBUG) { System.out.println("ClassMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$
+ consumeEmptyClassMemberDeclaration();
+ break;
- case 117 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON"); //$NON-NLS-1$
- consumeFieldDeclaration();
- break ;
-
- case 119 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator"); //$NON-NLS-1$
- consumeVariableDeclarators();
- break ;
-
- case 122 : // System.out.println("EnterVariable ::="); //$NON-NLS-1$
- consumeEnterVariable();
- break ;
-
- case 123 : // System.out.println("ExitVariableWithInitialization ::="); //$NON-NLS-1$
- consumeExitVariableWithInitialization();
- break ;
-
- case 124 : // System.out.println("ExitVariableWithoutInitialization ::="); //$NON-NLS-1$
- consumeExitVariableWithoutInitialization();
- break ;
-
- case 125 : // System.out.println("ForceNoDiet ::="); //$NON-NLS-1$
- consumeForceNoDiet();
- break ;
-
- case 126 : // System.out.println("RestoreDiet ::="); //$NON-NLS-1$
- consumeRestoreDiet();
- break ;
-
- case 131 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); //$NON-NLS-1$
- // set to true to consume a method with a body
- consumeMethodDeclaration(true);
- break ;
-
- case 132 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); //$NON-NLS-1$
- // set to false to consume a method without body
- consumeMethodDeclaration(false);
- break ;
-
- case 133 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters..."); //$NON-NLS-1$
- consumeMethodHeader();
- break ;
-
- case 134 : // System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); //$NON-NLS-1$
- consumeMethodHeaderName();
- break ;
-
- case 135 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN"); //$NON-NLS-1$
- consumeMethodHeaderParameters();
- break ;
-
- case 136 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); //$NON-NLS-1$
- consumeMethodHeaderExtendedDims();
- break ;
-
- case 137 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); //$NON-NLS-1$
- consumeMethodHeaderThrowsClause();
- break ;
-
- case 138 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters"); //$NON-NLS-1$
- consumeConstructorHeader();
- break ;
-
- case 139 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); //$NON-NLS-1$
- consumeConstructorHeaderName();
- break ;
-
- case 141 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter"); //$NON-NLS-1$
- consumeFormalParameterList();
- break ;
-
- case 142 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId"); //$NON-NLS-1$
- // the boolean is used to know if the modifiers should be reset
- consumeFormalParameter();
- break ;
-
- case 144 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); //$NON-NLS-1$
- consumeClassTypeList();
- break ;
-
- case 145 : // System.out.println("ClassTypeElt ::= ClassType"); //$NON-NLS-1$
- consumeClassTypeElt();
- break ;
-
- case 146 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE"); //$NON-NLS-1$
- consumeMethodBody();
- break ;
-
- case 147 : // System.out.println("NestedMethod ::="); //$NON-NLS-1$
- consumeNestedMethod();
- break ;
-
- case 148 : // System.out.println("StaticInitializer ::= StaticOnly Block"); //$NON-NLS-1$
- consumeStaticInitializer();
- break ;
-
- case 149 : // System.out.println("StaticOnly ::= static"); //$NON-NLS-1$
- consumeStaticOnly();
- break ;
-
- case 150 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); //$NON-NLS-1$
- consumeConstructorDeclaration() ;
- break ;
-
- case 151 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); //$NON-NLS-1$
- consumeInvalidConstructorDeclaration() ;
- break ;
-
- case 152 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN"); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This);
- break ;
-
- case 153 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt..."); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super);
- break ;
-
- case 154 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN..."); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super);
- break ;
-
- case 155 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN..."); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super);
- break ;
-
- case 156 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN..."); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This);
- break ;
-
- case 157 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN..."); //$NON-NLS-1$
- consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This);
- break ;
-
- case 158 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); //$NON-NLS-1$
- consumeInterfaceDeclaration();
- break ;
-
- case 159 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt"); //$NON-NLS-1$
- consumeInterfaceHeader();
- break ;
-
- case 160 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface Identifier"); //$NON-NLS-1$
- consumeInterfaceHeaderName();
- break ;
-
- case 162 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); //$NON-NLS-1$
- consumeInterfaceHeaderExtends();
- break ;
-
- case 165 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations..."); //$NON-NLS-1$
- consumeInterfaceMemberDeclarations();
- break ;
-
- case 166 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); //$NON-NLS-1$
- consumeEmptyInterfaceMemberDeclaration();
- break ;
-
- case 169 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration"); //$NON-NLS-1$
- ignoreMethodBody();
- break ;
-
- case 170 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader MethodBody"); //$NON-NLS-1$
- ignoreInvalidConstructorDeclaration(true);
- break ;
-
- case 171 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON"); //$NON-NLS-1$
- ignoreInvalidConstructorDeclaration(false);
- break ;
-
- case 177 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE"); //$NON-NLS-1$
- consumeEmptyArrayInitializer();
- break ;
-
- case 178 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE"); //$NON-NLS-1$
- consumeArrayInitializer();
- break ;
-
- case 179 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE"); //$NON-NLS-1$
- consumeArrayInitializer();
- break ;
-
- case 181 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); //$NON-NLS-1$
- consumeVariableInitializers();
- break ;
-
- case 182 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); //$NON-NLS-1$
- consumeBlock();
- break ;
-
- case 183 : // System.out.println("OpenBlock ::="); //$NON-NLS-1$
- consumeOpenBlock() ;
- break ;
-
- case 185 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement"); //$NON-NLS-1$
- consumeBlockStatements() ;
- break ;
-
- case 189 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration"); //$NON-NLS-1$
- ignoreInterfaceDeclaration();
- break ;
-
- case 190 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration..."); //$NON-NLS-1$
- consumeLocalVariableDeclarationStatement();
- break ;
-
- case 191 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators"); //$NON-NLS-1$
- consumeLocalVariableDeclaration();
- break ;
-
- case 192 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers..."); //$NON-NLS-1$
- consumeLocalVariableDeclaration();
- break ;
-
- case 193 : // System.out.println("PushModifiers ::="); //$NON-NLS-1$
- consumePushModifiers();
- break ;
-
- case 217 : // System.out.println("EmptyStatement ::= SEMICOLON"); //$NON-NLS-1$
- consumeEmptyStatement();
- break ;
-
- case 218 : // System.out.println("LabeledStatement ::= Identifier COLON Statement"); //$NON-NLS-1$
- consumeStatementLabel() ;
- break ;
-
- case 219 : // System.out.println("LabeledStatementNoShortIf ::= Identifier COLON StatementNoShortIf"); //$NON-NLS-1$
- consumeStatementLabel() ;
- break ;
-
- case 220 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); //$NON-NLS-1$
- consumeExpressionStatement();
- break ;
-
- case 229 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement"); //$NON-NLS-1$
- consumeStatementIfNoElse();
- break ;
-
- case 230 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); //$NON-NLS-1$
- consumeStatementIfWithElse();
- break ;
-
- case 231 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN..."); //$NON-NLS-1$
- consumeStatementIfWithElse();
- break ;
-
- case 232 : // System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN OpenBlock..."); //$NON-NLS-1$
- consumeStatementSwitch() ;
- break ;
-
- case 233 : // System.out.println("SwitchBlock ::= LBRACE RBRACE"); //$NON-NLS-1$
- consumeEmptySwitchBlock() ;
- break ;
-
- case 236 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE"); //$NON-NLS-1$
- consumeSwitchBlock() ;
- break ;
-
- case 238 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement"); //$NON-NLS-1$
- consumeSwitchBlockStatements() ;
- break ;
-
- case 239 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); //$NON-NLS-1$
- consumeSwitchBlockStatement() ;
- break ;
-
- case 241 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); //$NON-NLS-1$
- consumeSwitchLabels() ;
- break ;
-
- case 242 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON"); //$NON-NLS-1$
- consumeCaseLabel();
- break ;
-
- case 243 : // System.out.println("SwitchLabel ::= default COLON"); //$NON-NLS-1$
- consumeDefaultLabel();
- break ;
-
- case 244 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement"); //$NON-NLS-1$
- consumeStatementWhile() ;
- break ;
-
- case 245 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN..."); //$NON-NLS-1$
- consumeStatementWhile() ;
- break ;
-
- case 246 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN..."); //$NON-NLS-1$
- consumeStatementDo() ;
- break ;
-
- case 247 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt..."); //$NON-NLS-1$
- consumeStatementFor() ;
- break ;
-
- case 248 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON..."); //$NON-NLS-1$
- consumeStatementFor() ;
- break ;
-
- case 249 : // System.out.println("ForInit ::= StatementExpressionList"); //$NON-NLS-1$
- consumeForInit() ;
- break ;
-
- case 253 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA..."); //$NON-NLS-1$
- consumeStatementExpressionList() ;
- break ;
-
- case 254 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON"); //$NON-NLS-1$
- consumeSimpleAssertStatement() ;
- break ;
-
- case 255 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON"); //$NON-NLS-1$
- consumeAssertStatement() ;
- break ;
-
- case 256 : // System.out.println("BreakStatement ::= break SEMICOLON"); //$NON-NLS-1$
- consumeStatementBreak() ;
- break ;
-
- case 257 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON"); //$NON-NLS-1$
- consumeStatementBreakWithLabel() ;
- break ;
-
- case 258 : // System.out.println("ContinueStatement ::= continue SEMICOLON"); //$NON-NLS-1$
- consumeStatementContinue() ;
- break ;
-
- case 259 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); //$NON-NLS-1$
- consumeStatementContinueWithLabel() ;
- break ;
-
- case 260 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); //$NON-NLS-1$
- consumeStatementReturn() ;
- break ;
-
- case 261 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); //$NON-NLS-1$
- consumeStatementThrow();
-
- break ;
-
- case 262 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN"); //$NON-NLS-1$
- consumeStatementSynchronized();
- break ;
-
- case 263 : // System.out.println("OnlySynchronized ::= synchronized"); //$NON-NLS-1$
- consumeOnlySynchronized();
- break ;
-
- case 264 : // System.out.println("TryStatement ::= try TryBlock Catches"); //$NON-NLS-1$
- consumeStatementTry(false);
- break ;
-
- case 265 : // System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); //$NON-NLS-1$
- consumeStatementTry(true);
- break ;
-
- case 267 : // System.out.println("ExitTryBlock ::="); //$NON-NLS-1$
- consumeExitTryBlock();
- break ;
-
- case 269 : // System.out.println("Catches ::= Catches CatchClause"); //$NON-NLS-1$
- consumeCatches();
- break ;
-
- case 270 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block"); //$NON-NLS-1$
- consumeStatementCatch() ;
- break ;
-
- case 272 : // System.out.println("PushLPAREN ::= LPAREN"); //$NON-NLS-1$
- consumeLeftParen();
- break ;
-
- case 273 : // System.out.println("PushRPAREN ::= RPAREN"); //$NON-NLS-1$
- consumeRightParen();
- break ;
-
- case 278 : // System.out.println("PrimaryNoNewArray ::= this"); //$NON-NLS-1$
- consumePrimaryNoNewArrayThis();
- break ;
-
- case 279 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN"); //$NON-NLS-1$
- consumePrimaryNoNewArray();
- break ;
-
- case 282 : // System.out.println("PrimaryNoNewArray ::= Name DOT this"); //$NON-NLS-1$
- consumePrimaryNoNewArrayNameThis();
- break ;
-
- case 283 : // System.out.println("PrimaryNoNewArray ::= Name DOT super"); //$NON-NLS-1$
- consumePrimaryNoNewArrayNameSuper();
- break ;
-
- case 284 : // System.out.println("PrimaryNoNewArray ::= Name DOT class"); //$NON-NLS-1$
- consumePrimaryNoNewArrayName();
- break ;
-
- case 285 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class"); //$NON-NLS-1$
- consumePrimaryNoNewArrayArrayType();
- break ;
-
- case 286 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); //$NON-NLS-1$
- consumePrimaryNoNewArrayPrimitiveType();
- break ;
-
- case 289 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN"); //$NON-NLS-1$
- consumeAllocationHeader();
- break ;
-
- case 290 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN..."); //$NON-NLS-1$
- consumeClassInstanceCreationExpression();
- break ;
-
- case 291 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName..."); //$NON-NLS-1$
- consumeClassInstanceCreationExpressionQualified() ;
- break ;
-
- case 292 : // System.out.println("ClassInstanceCreationExpression ::=..."); //$NON-NLS-1$
- consumeClassInstanceCreationExpressionQualified() ;
- break ;
-
- case 293 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); //$NON-NLS-1$
- consumeClassInstanceCreationExpressionName() ;
- break ;
-
- case 294 : // System.out.println("ClassBodyopt ::="); //$NON-NLS-1$
- consumeClassBodyopt();
- break ;
-
- case 296 : // System.out.println("EnterAnonymousClassBody ::="); //$NON-NLS-1$
- consumeEnterAnonymousClassBody();
- break ;
-
- case 298 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); //$NON-NLS-1$
- consumeArgumentList();
- break ;
-
- case 299 : // System.out.println("ArrayCreationHeader ::= new PrimitiveType DimWithOrWithOutExprs"); //$NON-NLS-1$
- consumeArrayCreationHeader();
- break ;
-
- case 300 : // System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); //$NON-NLS-1$
- consumeArrayCreationHeader();
- break ;
-
- case 301 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new PrimitiveType..."); //$NON-NLS-1$
- consumeArrayCreationExpressionWithoutInitializer();
- break ;
-
- case 302 : // System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType..."); //$NON-NLS-1$
- consumeArrayCreationExpressionWithInitializer();
- break ;
-
- case 303 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new ClassOrInterfaceType..."); //$NON-NLS-1$
- consumeArrayCreationExpressionWithoutInitializer();
- break ;
-
- case 304 : // System.out.println("ArrayCreationWithArrayInitializer ::= new ClassOrInterfaceType..."); //$NON-NLS-1$
- consumeArrayCreationExpressionWithInitializer();
- break ;
-
- case 306 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr"); //$NON-NLS-1$
- consumeDimWithOrWithOutExprs();
- break ;
-
- case 308 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); //$NON-NLS-1$
- consumeDimWithOrWithOutExpr();
- break ;
-
- case 309 : // System.out.println("Dims ::= DimsLoop"); //$NON-NLS-1$
- consumeDims();
- break ;
-
- case 312 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); //$NON-NLS-1$
- consumeOneDimLoop();
- break ;
-
- case 313 : // System.out.println("FieldAccess ::= Primary DOT Identifier"); //$NON-NLS-1$
- consumeFieldAccess(false);
- break ;
-
- case 314 : // System.out.println("FieldAccess ::= super DOT Identifier"); //$NON-NLS-1$
- consumeFieldAccess(true);
- break ;
-
- case 315 : // System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); //$NON-NLS-1$
- consumeMethodInvocationName();
- break ;
-
- case 316 : // System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN ArgumentListopt"); //$NON-NLS-1$
- consumeMethodInvocationPrimary();
- break ;
-
- case 317 : // System.out.println("MethodInvocation ::= super DOT Identifier LPAREN ArgumentListopt..."); //$NON-NLS-1$
- consumeMethodInvocationSuper();
- break ;
-
- case 318 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); //$NON-NLS-1$
- consumeArrayAccess(true);
- break ;
-
- case 319 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET"); //$NON-NLS-1$
- consumeArrayAccess(false);
- break ;
-
- case 320 : // System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer LBRACKET..."); //$NON-NLS-1$
- consumeArrayAccess(false);
- break ;
-
- case 322 : // System.out.println("PostfixExpression ::= Name"); //$NON-NLS-1$
- consumePostfixExpression();
- break ;
-
- case 325 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.PLUS,true);
- break ;
-
- case 326 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.MINUS,true);
- break ;
-
- case 327 : // System.out.println("PushPosition ::="); //$NON-NLS-1$
- consumePushPosition();
- break ;
-
- case 330 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.PLUS);
- break ;
-
- case 331 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.MINUS);
- break ;
-
- case 333 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.PLUS,false);
- break ;
-
- case 334 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.MINUS,false);
- break ;
-
- case 336 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.TWIDDLE);
- break ;
-
- case 337 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression"); //$NON-NLS-1$
- consumeUnaryExpression(OperatorIds.NOT);
- break ;
-
- case 339 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN..."); //$NON-NLS-1$
- consumeCastExpression();
- break ;
-
- case 340 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); //$NON-NLS-1$
- consumeCastExpression();
- break ;
-
- case 341 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN..."); //$NON-NLS-1$
- consumeCastExpressionLL1();
- break ;
-
- case 342 : // System.out.println("InsideCastExpression ::="); //$NON-NLS-1$
- consumeInsideCastExpression();
- break ;
-
- case 343 : // System.out.println("InsideCastExpressionLL1 ::="); //$NON-NLS-1$
- consumeInsideCastExpressionLL1();
- break ;
-
- case 345 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.MULTIPLY);
- break ;
-
- case 346 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.DIVIDE);
- break ;
-
- case 347 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.REMAINDER);
- break ;
-
- case 349 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.PLUS);
- break ;
-
- case 350 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.MINUS);
- break ;
-
- case 352 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression"); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
- break ;
-
- case 353 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression"); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
- break ;
-
- case 354 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
- break ;
-
- case 356 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression"); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.LESS);
- break ;
-
- case 357 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.GREATER);
- break ;
-
- case 358 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.LESS_EQUAL);
- break ;
-
- case 359 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
- break ;
-
- case 360 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof..."); //$NON-NLS-1$
- consumeInstanceOfExpression(OperatorIds.INSTANCEOF);
- break ;
-
- case 362 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); //$NON-NLS-1$
- consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
- break ;
-
- case 363 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); //$NON-NLS-1$
- consumeEqualityExpression(OperatorIds.NOT_EQUAL);
- break ;
-
- case 365 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.AND);
- break ;
-
- case 367 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression"); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.XOR);
- break ;
-
- case 369 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.OR);
- break ;
-
- case 371 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.AND_AND);
- break ;
-
- case 373 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR..."); //$NON-NLS-1$
- consumeBinaryExpression(OperatorIds.OR_OR);
- break ;
-
- case 375 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION..."); //$NON-NLS-1$
- consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;
- break ;
-
- case 378 : // System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); //$NON-NLS-1$
- consumeAssignment();
- break ;
-
- case 380 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); //$NON-NLS-1$
- ignoreExpressionAssignment();
- break ;
-
- case 381 : // System.out.println("AssignmentOperator ::= EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(EQUAL);
- break ;
-
- case 382 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(MULTIPLY);
- break ;
-
- case 383 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(DIVIDE);
- break ;
-
- case 384 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(REMAINDER);
- break ;
-
- case 385 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(PLUS);
- break ;
-
- case 386 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(MINUS);
- break ;
-
- case 387 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(LEFT_SHIFT);
- break ;
-
- case 388 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(RIGHT_SHIFT);
- break ;
-
- case 389 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);
- break ;
-
- case 390 : // System.out.println("AssignmentOperator ::= AND_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(AND);
- break ;
-
- case 391 : // System.out.println("AssignmentOperator ::= XOR_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(XOR);
- break ;
-
- case 392 : // System.out.println("AssignmentOperator ::= OR_EQUAL"); //$NON-NLS-1$
- consumeAssignmentOperator(OR);
- break ;
-
- case 399 : // System.out.println("Expressionopt ::="); //$NON-NLS-1$
- consumeEmptyExpression();
- break ;
-
- case 403 : // System.out.println("ImportDeclarationsopt ::="); //$NON-NLS-1$
- consumeEmptyImportDeclarationsopt();
- break ;
-
- case 404 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations"); //$NON-NLS-1$
- consumeImportDeclarationsopt();
- break ;
-
- case 405 : // System.out.println("TypeDeclarationsopt ::="); //$NON-NLS-1$
- consumeEmptyTypeDeclarationsopt();
- break ;
-
- case 406 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations"); //$NON-NLS-1$
- consumeTypeDeclarationsopt();
- break ;
-
- case 407 : // System.out.println("ClassBodyDeclarationsopt ::="); //$NON-NLS-1$
- consumeEmptyClassBodyDeclarationsopt();
- break ;
-
- case 408 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations"); //$NON-NLS-1$
- consumeClassBodyDeclarationsopt();
- break ;
-
- case 409 : // System.out.println("Modifiersopt ::="); //$NON-NLS-1$
- consumeDefaultModifiers();
- break ;
-
- case 410 : // System.out.println("Modifiersopt ::= Modifiers"); //$NON-NLS-1$
- consumeModifiers();
- break ;
-
- case 411 : // System.out.println("BlockStatementsopt ::="); //$NON-NLS-1$
- consumeEmptyBlockStatementsopt();
- break ;
-
- case 413 : // System.out.println("Dimsopt ::="); //$NON-NLS-1$
- consumeEmptyDimsopt();
- break ;
-
- case 415 : // System.out.println("ArgumentListopt ::="); //$NON-NLS-1$
- consumeEmptyArgumentListopt();
- break ;
-
- case 419 : // System.out.println("FormalParameterListopt ::="); //$NON-NLS-1$
- consumeFormalParameterListopt();
- break ;
-
- case 423 : // System.out.println("InterfaceMemberDeclarationsopt ::="); //$NON-NLS-1$
- consumeEmptyInterfaceMemberDeclarationsopt();
- break ;
-
- case 424 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); //$NON-NLS-1$
- consumeInterfaceMemberDeclarationsopt();
- break ;
-
- case 425 : // System.out.println("NestedType ::="); //$NON-NLS-1$
- consumeNestedType();
- break ;
+ case 149 : if (DEBUG) { System.out.println("FieldDeclaration ::= Modifiersopt Type..."); } //$NON-NLS-1$
+ consumeFieldDeclaration();
+ break;
+
+ case 151 : if (DEBUG) { System.out.println("VariableDeclarators ::= VariableDeclarators COMMA..."); } //$NON-NLS-1$
+ consumeVariableDeclarators();
+ break;
+
+ case 154 : if (DEBUG) { System.out.println("EnterVariable ::="); } //$NON-NLS-1$
+ consumeEnterVariable();
+ break;
+
+ case 155 : if (DEBUG) { System.out.println("ExitVariableWithInitialization ::="); } //$NON-NLS-1$
+ consumeExitVariableWithInitialization();
+ break;
+
+ case 156 : if (DEBUG) { System.out.println("ExitVariableWithoutInitialization ::="); } //$NON-NLS-1$
+ consumeExitVariableWithoutInitialization();
+ break;
+
+ case 157 : if (DEBUG) { System.out.println("ForceNoDiet ::="); } //$NON-NLS-1$
+ consumeForceNoDiet();
+ break;
+
+ case 158 : if (DEBUG) { System.out.println("RestoreDiet ::="); } //$NON-NLS-1$
+ consumeRestoreDiet();
+ break;
+
+ case 163 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$
+ // set to true to consume a method with a body
+ consumeMethodDeclaration(true);
+ break;
+
+ case 164 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); } //$NON-NLS-1$
+ // set to false to consume a method without body
+ consumeMethodDeclaration(false);
+ break;
+
+ case 165 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); } //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ case 166 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt TypeParameters Type..."); } //$NON-NLS-1$
+ consumeMethodHeaderNameWithTypeParameters(false);
+ break;
+
+ case 167 : if (DEBUG) { System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN"); } //$NON-NLS-1$
+ consumeMethodHeaderName(false);
+ break;
+
+ case 168 : if (DEBUG) { System.out.println("MethodHeaderRightParen ::= RPAREN"); } //$NON-NLS-1$
+ consumeMethodHeaderRightParen();
+ break;
+
+ case 169 : if (DEBUG) { System.out.println("MethodHeaderExtendedDims ::= Dimsopt"); } //$NON-NLS-1$
+ consumeMethodHeaderExtendedDims();
+ break;
+
+ case 170 : if (DEBUG) { System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList"); } //$NON-NLS-1$
+ consumeMethodHeaderThrowsClause();
+ break;
+
+ case 171 : if (DEBUG) { System.out.println("ConstructorHeader ::= ConstructorHeaderName..."); } //$NON-NLS-1$
+ consumeConstructorHeader();
+ break;
+
+ case 172 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt TypeParameters..."); } //$NON-NLS-1$
+ consumeConstructorHeaderNameWithTypeParameters();
+ break;
+
+ case 173 : if (DEBUG) { System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN"); } //$NON-NLS-1$
+ consumeConstructorHeaderName();
+ break;
+
+ case 175 : if (DEBUG) { System.out.println("FormalParameterList ::= FormalParameterList COMMA..."); } //$NON-NLS-1$
+ consumeFormalParameterList();
+ break;
+
+ case 176 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type..."); } //$NON-NLS-1$
+ consumeFormalParameter(false);
+ break;
+
+ case 177 : if (DEBUG) { System.out.println("FormalParameter ::= Modifiersopt Type ELLIPSIS..."); } //$NON-NLS-1$
+ consumeFormalParameter(true);
+ break;
+
+ case 179 : if (DEBUG) { System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt"); } //$NON-NLS-1$
+ consumeClassTypeList();
+ break;
+
+ case 180 : if (DEBUG) { System.out.println("ClassTypeElt ::= ClassType"); } //$NON-NLS-1$
+ consumeClassTypeElt();
+ break;
+
+ case 181 : if (DEBUG) { System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt..."); } //$NON-NLS-1$
+ consumeMethodBody();
+ break;
+
+ case 182 : if (DEBUG) { System.out.println("NestedMethod ::="); } //$NON-NLS-1$
+ consumeNestedMethod();
+ break;
+
+ case 183 : if (DEBUG) { System.out.println("StaticInitializer ::= StaticOnly Block"); } //$NON-NLS-1$
+ consumeStaticInitializer();
+ break;
- case 426 : // System.out.println("ForInitopt ::="); //$NON-NLS-1$
- consumeEmptyForInitopt();
- break ;
-
- case 428 : // System.out.println("ForUpdateopt ::="); //$NON-NLS-1$
- consumeEmptyForUpdateopt();
- break ;
-
- case 432 : // System.out.println("Catchesopt ::="); //$NON-NLS-1$
- consumeEmptyCatchesopt();
- break ;
-
+ case 184 : if (DEBUG) { System.out.println("StaticOnly ::= static"); } //$NON-NLS-1$
+ consumeStaticOnly();
+ break;
+
+ case 185 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody"); } //$NON-NLS-1$
+ consumeConstructorDeclaration() ;
+ break;
+
+ case 186 : if (DEBUG) { System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON"); } //$NON-NLS-1$
+ consumeInvalidConstructorDeclaration() ;
+ break;
+
+ case 187 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= this LPAREN..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(0, THIS_CALL);
+ break;
+
+ case 188 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments this"); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(0,THIS_CALL);
+ break;
+
+ case 189 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= super LPAREN..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(0,SUPER_CALL);
+ break;
+
+ case 190 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= OnlyTypeArguments..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(0,SUPER_CALL);
+ break;
+
+ case 191 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT super..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(1, SUPER_CALL);
+ break;
+
+ case 192 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(1, SUPER_CALL);
+ break;
+
+ case 193 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN"); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(2, SUPER_CALL);
+ break;
+
+ case 194 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(2, SUPER_CALL);
+ break;
+
+ case 195 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT this..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(1, THIS_CALL);
+ break;
+
+ case 196 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Primary DOT..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(1, THIS_CALL);
+ break;
+
+ case 197 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN"); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocation(2, THIS_CALL);
+ break;
+
+ case 198 : if (DEBUG) { System.out.println("ExplicitConstructorInvocation ::= Name DOT..."); } //$NON-NLS-1$
+ consumeExplicitConstructorInvocationWithTypeArguments(2, THIS_CALL);
+ break;
+
+ case 199 : if (DEBUG) { System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody"); } //$NON-NLS-1$
+ consumeInterfaceDeclaration();
+ break;
+
+ case 200 : if (DEBUG) { System.out.println("InterfaceHeader ::= InterfaceHeaderName..."); } //$NON-NLS-1$
+ consumeInterfaceHeader();
+ break;
+
+ case 201 : if (DEBUG) { System.out.println("InterfaceHeaderName ::= InterfaceHeaderName1..."); } //$NON-NLS-1$
+ consumeTypeHeaderNameWithTypeParameters();
+ break;
+
+ case 203 : if (DEBUG) { System.out.println("InterfaceHeaderName1 ::= Modifiersopt interface..."); } //$NON-NLS-1$
+ consumeInterfaceHeaderName1();
+ break;
+
+ case 205 : if (DEBUG) { System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList"); } //$NON-NLS-1$
+ consumeInterfaceHeaderExtends();
+ break;
+
+ case 208 : if (DEBUG) { System.out.println("InterfaceMemberDeclarations ::=..."); } //$NON-NLS-1$
+ consumeInterfaceMemberDeclarations();
+ break;
+
+ case 209 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= SEMICOLON"); } //$NON-NLS-1$
+ consumeEmptyInterfaceMemberDeclaration();
+ break;
+
+ case 212 : if (DEBUG) { System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration"); } //$NON-NLS-1$
+ ignoreMethodBody();
+ break;
+
+ case 213 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$
+ ignoreInvalidConstructorDeclaration(true);
+ break;
+
+ case 214 : if (DEBUG) { System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader..."); } //$NON-NLS-1$
+ ignoreInvalidConstructorDeclaration(false);
+ break;
+
+ case 222 : if (DEBUG) { System.out.println("PushLeftBrace ::="); } //$NON-NLS-1$
+ consumePushLeftBrace();
+ break;
+
+ case 223 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace ,opt RBRACE"); } //$NON-NLS-1$
+ consumeEmptyArrayInitializer();
+ break;
+
+ case 224 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeArrayInitializer();
+ break;
+
+ case 225 : if (DEBUG) { System.out.println("ArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeArrayInitializer();
+ break;
+
+ case 227 : if (DEBUG) { System.out.println("VariableInitializers ::= VariableInitializers COMMA..."); } //$NON-NLS-1$
+ consumeVariableInitializers();
+ break;
+
+ case 228 : if (DEBUG) { System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE"); } //$NON-NLS-1$
+ consumeBlock();
+ break;
+
+ case 229 : if (DEBUG) { System.out.println("OpenBlock ::="); } //$NON-NLS-1$
+ consumeOpenBlock() ;
+ break;
+
+ case 231 : if (DEBUG) { System.out.println("BlockStatements ::= BlockStatements BlockStatement"); } //$NON-NLS-1$
+ consumeBlockStatements() ;
+ break;
+
+ case 235 : if (DEBUG) { System.out.println("BlockStatement ::= InvalidInterfaceDeclaration"); } //$NON-NLS-1$
+ ignoreInterfaceDeclaration();
+ break;
+
+ case 236 : if (DEBUG) { System.out.println("LocalVariableDeclarationStatement ::=..."); } //$NON-NLS-1$
+ consumeLocalVariableDeclarationStatement();
+ break;
+
+ case 237 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Type PushModifiers..."); } //$NON-NLS-1$
+ consumeLocalVariableDeclaration();
+ break;
+
+ case 238 : if (DEBUG) { System.out.println("LocalVariableDeclaration ::= Modifiers Type..."); } //$NON-NLS-1$
+ consumeLocalVariableDeclaration();
+ break;
+
+ case 239 : if (DEBUG) { System.out.println("PushModifiers ::="); } //$NON-NLS-1$
+ consumePushModifiers();
+ break;
+
+ case 240 : if (DEBUG) { System.out.println("PushModifiersForHeader ::="); } //$NON-NLS-1$
+ consumePushModifiersForHeader();
+ break;
+
+ case 241 : if (DEBUG) { System.out.println("PushRealModifiers ::="); } //$NON-NLS-1$
+ consumePushRealModifiers();
+ break;
+
+ case 267 : if (DEBUG) { System.out.println("EmptyStatement ::= SEMICOLON"); } //$NON-NLS-1$
+ consumeEmptyStatement();
+ break;
+
+ case 268 : if (DEBUG) { System.out.println("LabeledStatement ::= Identifier COLON Statement"); } //$NON-NLS-1$
+ consumeStatementLabel() ;
+ break;
+
+ case 269 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Identifier COLON..."); } //$NON-NLS-1$
+ consumeStatementLabel() ;
+ break;
+
+ case 270 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); } //$NON-NLS-1$
+ consumeExpressionStatement();
+ break;
+
+ case 279 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$
+ consumeStatementIfNoElse();
+ break;
+
+ case 280 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); } //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 281 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); } //$NON-NLS-1$
+ consumeStatementIfWithElse();
+ break;
+
+ case 282 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); } //$NON-NLS-1$
+ consumeStatementSwitch() ;
+ break;
+
+ case 283 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); } //$NON-NLS-1$
+ consumeEmptySwitchBlock() ;
+ break;
+
+ case 286 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); } //$NON-NLS-1$
+ consumeSwitchBlock() ;
+ break;
+
+ case 288 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); } //$NON-NLS-1$
+ consumeSwitchBlockStatements() ;
+ break;
+
+ case 289 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); } //$NON-NLS-1$
+ consumeSwitchBlockStatement() ;
+ break;
+
+ case 291 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); } //$NON-NLS-1$
+ consumeSwitchLabels() ;
+ break;
+
+ case 292 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); } //$NON-NLS-1$
+ consumeCaseLabel();
+ break;
+
+ case 293 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); } //$NON-NLS-1$
+ consumeDefaultLabel();
+ break;
+
+ case 294 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); } //$NON-NLS-1$
+ consumeStatementWhile() ;
+ break;
+
+ case 295 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); } //$NON-NLS-1$
+ consumeStatementWhile() ;
+ break;
+
+ case 296 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); } //$NON-NLS-1$
+ consumeStatementDo() ;
+ break;
+
+ case 297 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); } //$NON-NLS-1$
+ consumeStatementFor() ;
+ break;
+
+ case 298 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); } //$NON-NLS-1$
+ consumeStatementFor() ;
+ break;
+
+ case 299 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); } //$NON-NLS-1$
+ consumeForInit() ;
+ break;
+
+ case 303 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); } //$NON-NLS-1$
+ consumeStatementExpressionList() ;
+ break;
+
+ case 304 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); } //$NON-NLS-1$
+ consumeSimpleAssertStatement() ;
+ break;
+
+ case 305 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); } //$NON-NLS-1$
+ consumeAssertStatement() ;
+ break;
+
+ case 306 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementBreak() ;
+ break;
+
+ case 307 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementBreakWithLabel() ;
+ break;
+
+ case 308 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementContinue() ;
+ break;
+
+ case 309 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementContinueWithLabel() ;
+ break;
+
+ case 310 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementReturn() ;
+ break;
+
+ case 311 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); } //$NON-NLS-1$
+ consumeStatementThrow();
+ break;
+
+ case 312 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); } //$NON-NLS-1$
+ consumeStatementSynchronized();
+ break;
+
+ case 313 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); } //$NON-NLS-1$
+ consumeOnlySynchronized();
+ break;
+
+ case 314 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); } //$NON-NLS-1$
+ consumeStatementTry(false);
+ break;
+
+ case 315 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); } //$NON-NLS-1$
+ consumeStatementTry(true);
+ break;
+
+ case 317 : if (DEBUG) { System.out.println("ExitTryBlock ::="); } //$NON-NLS-1$
+ consumeExitTryBlock();
+ break;
+
+ case 319 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); } //$NON-NLS-1$
+ consumeCatches();
+ break;
+
+ case 320 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN..."); } //$NON-NLS-1$
+ consumeStatementCatch() ;
+ break;
+
+ case 322 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); } //$NON-NLS-1$
+ consumeLeftParen();
+ break;
+
+ case 323 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); } //$NON-NLS-1$
+ consumeRightParen();
+ break;
+
+ case 328 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayThis();
+ break;
+
+ case 329 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); } //$NON-NLS-1$
+ consumePrimaryNoNewArray();
+ break;
+
+ case 330 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayWithName();
+ break;
+
+ case 333 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayNameThis();
+ break;
+
+ case 334 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT super"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayNameSuper();
+ break;
+
+ case 335 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayName();
+ break;
+
+ case 336 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayArrayType();
+ break;
+
+ case 337 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayPrimitiveArrayType();
+ break;
+
+ case 338 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); } //$NON-NLS-1$
+ consumePrimaryNoNewArrayPrimitiveType();
+ break;
+
+ case 341 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); } //$NON-NLS-1$
+ consumeAllocationHeader();
+ break;
+
+ case 342 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionWithTypeArguments();
+ break;
+
+ case 343 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN"); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpression();
+ break;
+
+ case 344 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;
+ break;
+
+ case 345 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionQualified() ;
+ break;
+
+ case 346 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionQualified() ;
+ break;
+
+ case 347 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;
+ break;
+
+ case 348 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); } //$NON-NLS-1$
+ consumeClassInstanceCreationExpressionName() ;
+ break;
+
+ case 349 : if (DEBUG) { System.out.println("ClassBodyopt ::="); } //$NON-NLS-1$
+ consumeClassBodyopt();
+ break;
+
+ case 351 : if (DEBUG) { System.out.println("ClassBodySimpleNameopt ::="); } //$NON-NLS-1$
+ consumeClassBodyopt();
+ break;
+
+ case 353 : if (DEBUG) { System.out.println("EnterAnonymousClassBodySimpleName ::="); } //$NON-NLS-1$
+ consumeEnterAnonymousClassBodySimpleName();
+ break;
+
+ case 354 : if (DEBUG) { System.out.println("EnterAnonymousClassBody ::="); } //$NON-NLS-1$
+ consumeEnterAnonymousClassBody();
+ break;
+
+ case 356 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); } //$NON-NLS-1$
+ consumeArgumentList();
+ break;
+
+ case 357 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); } //$NON-NLS-1$
+ consumeArrayCreationHeader();
+ break;
+
+ case 358 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); } //$NON-NLS-1$
+ consumeArrayCreationHeader();
+ break;
+
+ case 359 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$
+ consumeArrayCreationExpressionWithoutInitializer();
+ break;
+
+ case 360 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); } //$NON-NLS-1$
+ consumeArrayCreationExpressionWithInitializer();
+ break;
+
+ case 361 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); } //$NON-NLS-1$
+ consumeArrayCreationExpressionWithoutInitializer();
+ break;
+
+ case 362 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); } //$NON-NLS-1$
+ consumeArrayCreationExpressionWithInitializer();
+ break;
+
+ case 364 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); } //$NON-NLS-1$
+ consumeDimWithOrWithOutExprs();
+ break;
+
+ case 366 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); } //$NON-NLS-1$
+ consumeDimWithOrWithOutExpr();
+ break;
+
+ case 367 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); } //$NON-NLS-1$
+ consumeDims();
+ break;
+
+ case 370 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); } //$NON-NLS-1$
+ consumeOneDimLoop();
+ break;
+
+ case 371 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); } //$NON-NLS-1$
+ consumeFieldAccess(false);
+ break;
+
+ case 372 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); } //$NON-NLS-1$
+ consumeFieldAccess(true);
+ break;
+
+ case 373 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$
+ consumeMethodInvocationName();
+ break;
+
+ case 374 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); } //$NON-NLS-1$
+ consumeMethodInvocationNameWithTypeArguments();
+ break;
+
+ case 375 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); } //$NON-NLS-1$
+ consumeMethodInvocationPrimaryWithTypeArguments();
+ break;
+
+ case 376 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); } //$NON-NLS-1$
+ consumeMethodInvocationPrimary();
+ break;
+
+ case 377 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); } //$NON-NLS-1$
+ consumeMethodInvocationSuperWithTypeArguments();
+ break;
+
+ case 378 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); } //$NON-NLS-1$
+ consumeMethodInvocationSuper();
+ break;
+
+ case 379 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); } //$NON-NLS-1$
+ consumeArrayAccess(true);
+ break;
+
+ case 380 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); } //$NON-NLS-1$
+ consumeArrayAccess(false);
+ break;
+
+ case 381 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); } //$NON-NLS-1$
+ consumeArrayAccess(false);
+ break;
+
+ case 383 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); } //$NON-NLS-1$
+ consumePostfixExpression();
+ break;
+
+ case 386 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS,true);
+ break;
+
+ case 387 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS,true);
+ break;
+
+ case 388 : if (DEBUG) { System.out.println("PushPosition ::="); } //$NON-NLS-1$
+ consumePushPosition();
+ break;
+
+ case 391 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 392 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 394 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS,false);
+ break;
+
+ case 395 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS,false);
+ break;
+
+ case 397 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TWIDDLE);
+ break;
+
+ case 398 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.NOT);
+ break;
+
+ case 400 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); } //$NON-NLS-1$
+ consumeCastExpressionWithPrimitiveType();
+ break;
+
+ case 401 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$
+ consumeCastExpressionWithGenericsArray();
+ break;
+
+ case 402 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); } //$NON-NLS-1$
+ consumeCastExpressionWithQualifiedGenericsArray();
+ break;
+
+ case 403 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); } //$NON-NLS-1$
+ consumeCastExpressionLL1();
+ break;
+
+ case 404 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); } //$NON-NLS-1$
+ consumeCastExpressionWithNameArray();
+ break;
+
+ case 405 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); } //$NON-NLS-1$
+ consumeOnlyTypeArgumentsForCastExpression();
+ break;
+
+ case 406 : if (DEBUG) { System.out.println("InsideCastExpression ::="); } //$NON-NLS-1$
+ consumeInsideCastExpression();
+ break;
+
+ case 407 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); } //$NON-NLS-1$
+ consumeInsideCastExpressionLL1();
+ break;
+
+ case 408 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); } //$NON-NLS-1$
+ consumeInsideCastExpressionWithQualifiedGenerics();
+ break;
+
+ case 410 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MULTIPLY);
+ break;
+
+ case 411 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.DIVIDE);
+ break;
+
+ case 412 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.REMAINDER);
+ break;
+
+ case 414 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 415 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 417 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
+ break;
+
+ case 418 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
+ break;
+
+ case 419 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 421 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS);
+ break;
+
+ case 422 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER);
+ break;
+
+ case 423 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 424 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 426 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); } //$NON-NLS-1$
+ consumeInstanceOfExpression(OperatorIds.INSTANCEOF);
+ break;
+
+ case 428 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); } //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 429 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); } //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 431 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND);
+ break;
+
+ case 433 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.XOR);
+ break;
+
+ case 435 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR);
+ break;
+
+ case 437 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND_AND);
+ break;
+
+ case 439 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR_OR);
+ break;
+
+ case 441 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); } //$NON-NLS-1$
+ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;
+ break;
+
+ case 444 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); } //$NON-NLS-1$
+ consumeAssignment();
+ break;
+
+ case 446 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); } //$NON-NLS-1$
+ ignoreExpressionAssignment();
+ break;
+
+ case 447 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(EQUAL);
+ break;
+
+ case 448 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(MULTIPLY);
+ break;
+
+ case 449 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(DIVIDE);
+ break;
+
+ case 450 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(REMAINDER);
+ break;
+
+ case 451 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(PLUS);
+ break;
+
+ case 452 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(MINUS);
+ break;
+
+ case 453 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(LEFT_SHIFT);
+ break;
+
+ case 454 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(RIGHT_SHIFT);
+ break;
+
+ case 455 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 456 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(AND);
+ break;
+
+ case 457 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(XOR);
+ break;
+
+ case 458 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); } //$NON-NLS-1$
+ consumeAssignmentOperator(OR);
+ break;
+
+ case 462 : if (DEBUG) { System.out.println("Expressionopt ::="); } //$NON-NLS-1$
+ consumeEmptyExpression();
+ break;
+
+ case 467 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); } //$NON-NLS-1$
+ consumeEmptyClassBodyDeclarationsopt();
+ break;
+
+ case 468 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$
+ consumeClassBodyDeclarationsopt();
+ break;
+
+ case 469 : if (DEBUG) { System.out.println("Modifiersopt ::="); } //$NON-NLS-1$
+ consumeDefaultModifiers();
+ break;
+
+ case 470 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); } //$NON-NLS-1$
+ consumeModifiers();
+ break;
+
+ case 471 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); } //$NON-NLS-1$
+ consumeEmptyBlockStatementsopt();
+ break;
+
+ case 473 : if (DEBUG) { System.out.println("Dimsopt ::="); } //$NON-NLS-1$
+ consumeEmptyDimsopt();
+ break;
+
+ case 475 : if (DEBUG) { System.out.println("ArgumentListopt ::="); } //$NON-NLS-1$
+ consumeEmptyArgumentListopt();
+ break;
+
+ case 479 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); } //$NON-NLS-1$
+ consumeFormalParameterListopt();
+ break;
+
+ case 483 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); } //$NON-NLS-1$
+ consumeEmptyInterfaceMemberDeclarationsopt();
+ break;
+
+ case 484 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); } //$NON-NLS-1$
+ consumeInterfaceMemberDeclarationsopt();
+ break;
+
+ case 485 : if (DEBUG) { System.out.println("NestedType ::="); } //$NON-NLS-1$
+ consumeNestedType();
+ break;
+
+ case 486 : if (DEBUG) { System.out.println("ForInitopt ::="); } //$NON-NLS-1$
+ consumeEmptyForInitopt();
+ break;
+
+ case 488 : if (DEBUG) { System.out.println("ForUpdateopt ::="); } //$NON-NLS-1$
+ consumeEmptyForUpdateopt();
+ break;
+
+ case 492 : if (DEBUG) { System.out.println("Catchesopt ::="); } //$NON-NLS-1$
+ consumeEmptyCatchesopt();
+ break;
+
+ case 494 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); } //$NON-NLS-1$
+ consumeEnumDeclaration();
+ break;
+
+ case 495 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); } //$NON-NLS-1$
+ consumeEnumHeader();
+ break;
+
+ case 496 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); } //$NON-NLS-1$
+ consumeEnumHeaderName();
+ break;
+
+ case 497 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); } //$NON-NLS-1$
+ consumeEnumBodyNoConstants();
+ break;
+
+ case 498 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); } //$NON-NLS-1$
+ consumeEnumBodyNoConstants();
+ break;
+
+ case 499 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); } //$NON-NLS-1$
+ consumeEnumBodyWithConstants();
+ break;
+
+ case 500 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); } //$NON-NLS-1$
+ consumeEnumBodyWithConstants();
+ break;
+
+ case 502 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); } //$NON-NLS-1$
+ consumeEnumConstants();
+ break;
+
+ case 503 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); } //$NON-NLS-1$
+ consumeEnumConstantHeaderName();
+ break;
+
+ case 504 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); } //$NON-NLS-1$
+ consumeEnumConstantHeader();
+ break;
+
+ case 505 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); } //$NON-NLS-1$
+ consumeEnumConstantWithClassBody();
+ break;
+
+ case 506 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); } //$NON-NLS-1$
+ consumeEnumConstantNoClassBody();
+ break;
+
+ case 507 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); } //$NON-NLS-1$
+ consumeArguments();
+ break;
+
+ case 508 : if (DEBUG) { System.out.println("Argumentsopt ::="); } //$NON-NLS-1$
+ consumeEmptyArguments();
+ break;
+
+ case 510 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); } //$NON-NLS-1$
+ consumeEnumDeclarations();
+ break;
+
+ case 511 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); } //$NON-NLS-1$
+ consumeEmptyEnumDeclarations();
+ break;
+
+ case 513 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); } //$NON-NLS-1$
+ consumeEnhancedForStatement();
+ break;
+
+ case 514 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); } //$NON-NLS-1$
+ consumeEnhancedForStatement();
+ break;
+
+ case 515 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::= for LPAREN Type..."); } //$NON-NLS-1$
+ consumeEnhancedForStatementHeader(false);
+ break;
+
+ case 516 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::= for LPAREN Modifiers Type"); } //$NON-NLS-1$
+ consumeEnhancedForStatementHeader(true);
+ break;
+
+ case 517 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); } //$NON-NLS-1$
+ consumeImportDeclaration();
+ break;
+
+ case 518 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); } //$NON-NLS-1$
+ consumeSingleStaticImportDeclarationName();
+ break;
+
+ case 519 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); } //$NON-NLS-1$
+ consumeImportDeclaration();
+ break;
+
+ case 520 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); } //$NON-NLS-1$
+ consumeStaticImportOnDemandDeclarationName();
+ break;
+
+ case 521 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$
+ consumeTypeArguments();
+ break;
+
+ case 522 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); } //$NON-NLS-1$
+ consumeOnlyTypeArguments();
+ break;
+
+ case 524 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$
+ consumeTypeArgumentList1();
+ break;
+
+ case 526 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); } //$NON-NLS-1$
+ consumeTypeArgumentList();
+ break;
+
+ case 527 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); } //$NON-NLS-1$
+ consumeTypeArgument();
+ break;
+
+ case 531 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); } //$NON-NLS-1$
+ consumeReferenceType1();
+ break;
+
+ case 532 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$
+ consumeTypeArgumentReferenceType1();
+ break;
+
+ case 534 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$
+ consumeTypeArgumentList2();
+ break;
+
+ case 537 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); } //$NON-NLS-1$
+ consumeReferenceType2();
+ break;
+
+ case 538 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); } //$NON-NLS-1$
+ consumeTypeArgumentReferenceType2();
+ break;
+
+ case 540 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); } //$NON-NLS-1$
+ consumeTypeArgumentList3();
+ break;
+
+ case 543 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$
+ consumeReferenceType3();
+ break;
+
+ case 544 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION"); } //$NON-NLS-1$
+ consumeWildcard();
+ break;
+
+ case 545 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION WildcardBounds"); } //$NON-NLS-1$
+ consumeWildcardWithBounds();
+ break;
+
+ case 546 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); } //$NON-NLS-1$
+ consumeWildcardBoundsExtends();
+ break;
+
+ case 547 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); } //$NON-NLS-1$
+ consumeWildcardBoundsSuper();
+ break;
+
+ case 548 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION GREATER"); } //$NON-NLS-1$
+ consumeWildcard1();
+ break;
+
+ case 549 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION WildcardBounds1"); } //$NON-NLS-1$
+ consumeWildcard1WithBounds();
+ break;
+
+ case 550 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); } //$NON-NLS-1$
+ consumeWildcardBounds1Extends();
+ break;
+
+ case 551 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); } //$NON-NLS-1$
+ consumeWildcardBounds1Super();
+ break;
+
+ case 552 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION RIGHT_SHIFT"); } //$NON-NLS-1$
+ consumeWildcard2();
+ break;
+
+ case 553 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION WildcardBounds2"); } //$NON-NLS-1$
+ consumeWildcard2WithBounds();
+ break;
+
+ case 554 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); } //$NON-NLS-1$
+ consumeWildcardBounds2Extends();
+ break;
+
+ case 555 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); } //$NON-NLS-1$
+ consumeWildcardBounds2Super();
+ break;
+
+ case 556 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION UNSIGNED_RIGHT_SHIFT"); } //$NON-NLS-1$
+ consumeWildcard3();
+ break;
+
+ case 557 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION WildcardBounds3"); } //$NON-NLS-1$
+ consumeWildcard3WithBounds();
+ break;
+
+ case 558 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); } //$NON-NLS-1$
+ consumeWildcardBounds3Extends();
+ break;
+
+ case 559 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); } //$NON-NLS-1$
+ consumeWildcardBounds3Super();
+ break;
+
+ case 560 : if (DEBUG) { System.out.println("TypeParameterHeader ::= Identifier"); } //$NON-NLS-1$
+ consumeTypeParameterHeader();
+ break;
+
+ case 561 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); } //$NON-NLS-1$
+ consumeTypeParameters();
+ break;
+
+ case 563 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); } //$NON-NLS-1$
+ consumeTypeParameterList();
+ break;
+
+ case 565 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$
+ consumeTypeParameterWithExtends();
+ break;
+
+ case 566 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); } //$NON-NLS-1$
+ consumeTypeParameterWithExtendsAndBounds();
+ break;
+
+ case 568 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); } //$NON-NLS-1$
+ consumeAdditionalBoundList();
+ break;
+
+ case 569 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); } //$NON-NLS-1$
+ consumeAdditionalBound();
+ break;
+
+ case 571 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); } //$NON-NLS-1$
+ consumeTypeParameterList1();
+ break;
+
+ case 572 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); } //$NON-NLS-1$
+ consumeTypeParameter1();
+ break;
+
+ case 573 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$
+ consumeTypeParameter1WithExtends();
+ break;
+
+ case 574 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); } //$NON-NLS-1$
+ consumeTypeParameter1WithExtendsAndBounds();
+ break;
+
+ case 576 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); } //$NON-NLS-1$
+ consumeAdditionalBoundList1();
+ break;
+
+ case 577 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); } //$NON-NLS-1$
+ consumeAdditionalBound1();
+ break;
+
+ case 583 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 584 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 587 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.TWIDDLE);
+ break;
+
+ case 588 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); } //$NON-NLS-1$
+ consumeUnaryExpression(OperatorIds.NOT);
+ break;
+
+ case 591 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MULTIPLY);
+ break;
+
+ case 592 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.MULTIPLY);
+ break;
+
+ case 593 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.DIVIDE);
+ break;
+
+ case 594 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.DIVIDE);
+ break;
+
+ case 595 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.REMAINDER);
+ break;
+
+ case 596 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.REMAINDER);
+ break;
+
+ case 598 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.PLUS);
+ break;
+
+ case 599 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.PLUS);
+ break;
+
+ case 600 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.MINUS);
+ break;
+
+ case 601 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.MINUS);
+ break;
+
+ case 603 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LEFT_SHIFT);
+ break;
+
+ case 604 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT);
+ break;
+
+ case 605 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);
+ break;
+
+ case 606 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT);
+ break;
+
+ case 607 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 608 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT);
+ break;
+
+ case 610 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS);
+ break;
+
+ case 611 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.LESS);
+ break;
+
+ case 612 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER);
+ break;
+
+ case 613 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.GREATER);
+ break;
+
+ case 614 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 615 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL);
+ break;
+
+ case 616 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 617 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL);
+ break;
+
+ case 619 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); } //$NON-NLS-1$
+ consumeInstanceOfExpressionWithName(OperatorIds.INSTANCEOF);
+ break;
+
+ case 620 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeInstanceOfExpression(OperatorIds.INSTANCEOF);
+ break;
+
+ case 622 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 623 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); } //$NON-NLS-1$
+ consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL);
+ break;
+
+ case 624 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeEqualityExpression(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 625 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); } //$NON-NLS-1$
+ consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL);
+ break;
+
+ case 627 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND);
+ break;
+
+ case 628 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.AND);
+ break;
+
+ case 630 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.XOR);
+ break;
+
+ case 631 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.XOR);
+ break;
+
+ case 633 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR);
+ break;
+
+ case 634 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.OR);
+ break;
+
+ case 636 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.AND_AND);
+ break;
+
+ case 637 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.AND_AND);
+ break;
+
+ case 639 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeBinaryExpression(OperatorIds.OR_OR);
+ break;
+
+ case 640 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); } //$NON-NLS-1$
+ consumeBinaryExpressionWithName(OperatorIds.OR_OR);
+ break;
+
+ case 642 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); } //$NON-NLS-1$
+ consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;
+ break;
+
+ case 643 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); } //$NON-NLS-1$
+ consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ;
+ break;
+
+ case 647 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); } //$NON-NLS-1$
+ consumeAnnotationTypeDeclarationHeaderName() ;
+ break;
+
+ case 648 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); } //$NON-NLS-1$
+ consumeAnnotationTypeDeclarationHeaderName() ;
+ break;
+
+ case 649 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); } //$NON-NLS-1$
+ consumeAnnotationTypeDeclarationHeader() ;
+ break;
+
+ case 650 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); } //$NON-NLS-1$
+ consumeAnnotationTypeDeclaration() ;
+ break;
+
+ case 652 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); } //$NON-NLS-1$
+ consumeEmptyAnnotationTypeMemberDeclarationsopt() ;
+ break;
+
+ case 655 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); } //$NON-NLS-1$
+ consumeAnnotationTypeMemberDeclarations() ;
+ break;
+
+ case 656 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); } //$NON-NLS-1$
+ consumeMethodHeaderNameWithTypeParameters(true);
+ break;
+
+ case 657 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$
+ consumeMethodHeaderName(true);
+ break;
+
+ case 658 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); } //$NON-NLS-1$
+ consumeEmptyMethodHeaderDefaultValue() ;
+ break;
+
+ case 659 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); } //$NON-NLS-1$
+ consumeMethodHeaderDefaultValue();
+ break;
+
+ case 660 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); } //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ case 661 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); } //$NON-NLS-1$
+ consumeAnnotationTypeMemberDeclaration() ;
+ break;
+
+ case 669 : if (DEBUG) { System.out.println("AnnotationName ::= AT Name"); } //$NON-NLS-1$
+ consumeAnnotationName() ;
+ break;
+
+ case 670 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$
+ consumeNormalAnnotation() ;
+ break;
+
+ case 671 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); } //$NON-NLS-1$
+ consumeEmptyMemberValuePairsopt() ;
+ break;
+
+ case 674 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); } //$NON-NLS-1$
+ consumeMemberValuePairs() ;
+ break;
+
+ case 675 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL MemberValue"); } //$NON-NLS-1$
+ consumeMemberValuePair() ;
+ break;
+
+ case 677 : if (DEBUG) { System.out.println("MemberValue ::= Name"); } //$NON-NLS-1$
+ consumeMemberValueAsName() ;
+ break;
+
+ case 680 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeMemberValueArrayInitializer() ;
+ break;
+
+ case 681 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeMemberValueArrayInitializer() ;
+ break;
+
+ case 682 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeEmptyMemberValueArrayInitializer() ;
+ break;
+
+ case 683 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); } //$NON-NLS-1$
+ consumeEmptyMemberValueArrayInitializer() ;
+ break;
+
+ case 685 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); } //$NON-NLS-1$
+ consumeMemberValues() ;
+ break;
+
+ case 686 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); } //$NON-NLS-1$
+ consumeMarkerAnnotation() ;
+ break;
+
+ case 687 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); } //$NON-NLS-1$
+ consumeSingleMemberAnnotation() ;
+ break;
+
+ case 688 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); } //$NON-NLS-1$
+ consumeRecoveryMethodHeaderNameWithTypeParameters();
+ break;
+
+ case 689 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); } //$NON-NLS-1$
+ consumeRecoveryMethodHeaderName();
+ break;
+
+ case 690 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
+ case 691 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); } //$NON-NLS-1$
+ consumeMethodHeader();
+ break;
+
}
}
protected void consumeSimpleAssertStatement() {
@@ -3494,23 +6129,82 @@ protected void consumeSimpleAssertStatement() {
this.expressionLengthPtr--;
pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));
}
-
-protected void consumeSingleTypeImportDeclaration() {
- // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+protected void consumeSingleMemberAnnotation() {
+ // SingleMemberAnnotation ::= '@' Name '(' MemberValue ')'
+ SingleMemberAnnotation singleMemberAnnotation = null;
+ int length = this.identifierLengthStack[this.identifierLengthPtr--];
+ TypeReference typeReference;
+ if (length == 1) {
+ typeReference = new SingleTypeReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
+ } else {
+ char[][] tokens = new char[length][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ this.identifierPositionStack,
+ this.identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ typeReference = new QualifiedTypeReference(tokens, positions);
+ }
+ singleMemberAnnotation = new SingleMemberAnnotation(typeReference, this.intStack[this.intPtr--]);
+ singleMemberAnnotation.memberValue = this.expressionStack[this.expressionPtr--];
+ this.expressionLengthPtr--;
+ int sourceStart = singleMemberAnnotation.sourceStart;
+ if (this.modifiersSourceStart < 0) {
+ this.modifiersSourceStart = sourceStart;
+ } else if (this.modifiersSourceStart > sourceStart) {
+ this.modifiersSourceStart = sourceStart;
+ }
+ singleMemberAnnotation.declarationSourceEnd = this.rParenPos;
+ pushOnExpressionStack(singleMemberAnnotation);
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ this.problemReporter().invalidUsageOfAnnotation(singleMemberAnnotation);
+ }
+}
+protected void consumeSingleStaticImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' 'static' Name
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
- ImportReference impt = (ImportReference) this.astStack[this.astPtr];
- // flush comments defined prior to import statements
- impt.declarationEnd = this.endStatementPosition;
- impt.declarationSourceEnd =
- this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, false, AccStatic));
+
+ this.modifiers = AccDefault;
+ this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+ if(this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ impt.modifiers = AccDefault; // convert the static import reference to a non-static importe reference
+ this.problemReporter().invalidUsageOfStaticImports(impt);
+ }
+
// recovery
- if (this.currentElement != null) {
- this.lastCheckPoint = impt.declarationSourceEnd + 1;
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
this.currentElement = this.currentElement.add(impt, 0);
this.lastIgnoredToken = -1;
- this.restartRecovery = true;
- // used to avoid branching back into the regular automaton
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
}
}
protected void consumeSingleTypeImportDeclarationName() {
@@ -3533,7 +6227,7 @@ protected void consumeSingleTypeImportDeclarationName() {
impt.declarationSourceEnd = impt.sourceEnd;
}
impt.declarationEnd = impt.declarationSourceEnd;
- //endPosition is just before the ;
+ //this.endPosition is just before the ;
impt.declarationSourceStart = this.intStack[this.intPtr--];
// recovery
@@ -3546,13 +6240,13 @@ protected void consumeSingleTypeImportDeclarationName() {
}
protected void consumeStatementBreak() {
// BreakStatement ::= 'break' ';'
- // break pushs a position on intStack in case there is no label
+ // break pushs a position on this.intStack in case there is no label
pushOnAstStack(new BreakStatement(null, this.intStack[this.intPtr--], this.endPosition));
}
protected void consumeStatementBreakWithLabel() {
// BreakStatement ::= 'break' Identifier ';'
- // break pushs a position on intStack in case there is no label
+ // break pushs a position on this.intStack in case there is no label
pushOnAstStack(
new BreakStatement(
@@ -3575,7 +6269,7 @@ protected void consumeStatementCatch() {
}
protected void consumeStatementContinue() {
// ContinueStatement ::= 'continue' ';'
- // continue pushs a position on intStack in case there is no label
+ // continue pushs a position on this.intStack in case there is no label
pushOnAstStack(
new ContinueStatement(
@@ -3585,7 +6279,7 @@ protected void consumeStatementContinue() {
}
protected void consumeStatementContinueWithLabel() {
// ContinueStatement ::= 'continue' Identifier ';'
- // continue pushs a position on intStack in case there is no label
+ // continue pushs a position on this.intStack in case there is no label
pushOnAstStack(
new ContinueStatement(
@@ -3597,7 +6291,7 @@ protected void consumeStatementContinueWithLabel() {
protected void consumeStatementDo() {
// DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
- //the 'while' pushes a value on intStack that we need to remove
+ //the 'while' pushes a value on this.intStack that we need to remove
this.intPtr--;
Statement statement = (Statement) this.astStack[this.astPtr];
@@ -3647,7 +6341,7 @@ protected void consumeStatementFor() {
inits = null;
scope = false;
} else {
- if (length == -1) { //on expressionStack
+ if (length == -1) { //on this.expressionStack
scope = false;
length = this.expressionLengthStack[this.expressionLengthPtr--];
this.expressionPtr -= length;
@@ -3657,7 +6351,7 @@ protected void consumeStatementFor() {
inits = new Statement[length],
0,
length);
- } else { //on astStack
+ } else { //on this.astStack
this.astPtr -= length;
System.arraycopy(
this.astStack,
@@ -3724,7 +6418,7 @@ protected void consumeStatementLabel() {
}
protected void consumeStatementReturn() {
// ReturnStatement ::= 'return' Expressionopt ';'
- // return pushs a position on intStack in case there is no expression
+ // return pushs a position on this.intStack in case there is no expression
if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) {
pushOnAstStack(
@@ -3842,6 +6536,46 @@ protected void consumeStatementWhile() {
this.intStack[this.intPtr--],
this.endStatementPosition);
}
+protected void consumeStaticImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' 'static' Name '.' '*'
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, true, AccStatic));
+
+ this.modifiers = AccDefault;
+ this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ impt.modifiers = AccDefault; // convert the static import reference to a non-static importe reference
+ this.problemReporter().invalidUsageOfStaticImports(impt);
+ }
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+}
protected void consumeStaticInitializer() {
// StaticInitializer ::= StaticOnly Block
//push an Initializer
@@ -3927,110 +6661,115 @@ protected void consumeToken(int type) {
switch (type) {
case TokenNameIdentifier :
pushIdentifier();
- if (this.scanner.useAssertAsAnIndentifier) {
+ if (this.scanner.useAssertAsAnIndentifier &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
long positions = this.identifierPositionStack[this.identifierPtr];
problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions);
}
-// this.scanner.commentPtr = -1;
+ if (this.scanner.useEnumAsAnIndentifier &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ long positions = this.identifierPositionStack[this.identifierPtr];
+ problemReporter().useEnumAsAnIdentifier((int) (positions >>> 32), (int) positions);
+ }
break;
case TokenNameinterface :
- adjustInterfaceModifiers();
//'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too....
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNameabstract :
checkAndSetModifiers(AccAbstract);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamestrictfp :
checkAndSetModifiers(AccStrictfp);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamefinal :
checkAndSetModifiers(AccFinal);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamenative :
checkAndSetModifiers(AccNative);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNameprivate :
checkAndSetModifiers(AccPrivate);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNameprotected :
checkAndSetModifiers(AccProtected);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamepublic :
checkAndSetModifiers(AccPublic);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNametransient :
checkAndSetModifiers(AccTransient);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamevolatile :
checkAndSetModifiers(AccVolatile);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamestatic :
checkAndSetModifiers(AccStatic);
+ pushOnExpressionStackLengthStack(0);
break;
case TokenNamesynchronized :
this.synchronizedBlockSourceStart = this.scanner.startPosition;
checkAndSetModifiers(AccSynchronized);
+ pushOnExpressionStackLengthStack(0);
break;
//==============================
case TokenNamevoid :
pushIdentifier(-T_void);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
//push a default dimension while void is not part of the primitive
//declaration baseType and so takes the place of a type without getting into
- //regular type parsing that generates a dimension on intStack
+ //regular type parsing that generates a dimension on this.intStack
case TokenNameboolean :
pushIdentifier(-T_boolean);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNamebyte :
pushIdentifier(-T_byte);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNamechar :
pushIdentifier(-T_char);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNamedouble :
pushIdentifier(-T_double);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNamefloat :
pushIdentifier(-T_float);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNameint :
pushIdentifier(-T_int);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNamelong :
pushIdentifier(-T_long);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
case TokenNameshort :
pushIdentifier(-T_short);
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
-// this.scanner.commentPtr = -1;
break;
//==============================
case TokenNameIntegerLiteral :
@@ -4039,7 +6778,6 @@ protected void consumeToken(int type) {
this.scanner.getCurrentTokenSource(),
this.scanner.startPosition,
this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNameLongLiteral :
pushOnExpressionStack(
@@ -4047,7 +6785,6 @@ protected void consumeToken(int type) {
this.scanner.getCurrentTokenSource(),
this.scanner.startPosition,
this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNameFloatingPointLiteral :
pushOnExpressionStack(
@@ -4055,7 +6792,6 @@ protected void consumeToken(int type) {
this.scanner.getCurrentTokenSource(),
this.scanner.startPosition,
this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNameDoubleLiteral :
pushOnExpressionStack(
@@ -4063,7 +6799,6 @@ protected void consumeToken(int type) {
this.scanner.getCurrentTokenSource(),
this.scanner.startPosition,
this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNameCharacterLiteral :
pushOnExpressionStack(
@@ -4071,7 +6806,6 @@ protected void consumeToken(int type) {
this.scanner.getCurrentTokenSource(),
this.scanner.startPosition,
this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNameStringLiteral :
StringLiteral stringLiteral = new StringLiteral(
@@ -4079,12 +6813,10 @@ protected void consumeToken(int type) {
this.scanner.startPosition,
this.scanner.currentPosition - 1);
pushOnExpressionStack(stringLiteral);
-// this.scanner.commentPtr = -1;
break;
case TokenNamefalse :
pushOnExpressionStack(
new FalseLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1));
-// this.scanner.commentPtr = -1;
break;
case TokenNametrue :
pushOnExpressionStack(
@@ -4125,16 +6857,24 @@ protected void consumeToken(int type) {
pushOnIntStack(this.scanner.currentPosition - 1);
pushOnIntStack(this.scanner.startPosition);
break;
+ case TokenNameenum :
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ pushOnIntStack(this.scanner.startPosition);
+ break;
case TokenNamedefault :
pushOnIntStack(this.scanner.startPosition);
pushOnIntStack(this.scanner.currentPosition - 1);
break;
//let extra semantic action decide when to push
case TokenNameRBRACKET :
+ this.endPosition = this.scanner.startPosition;
+ this.endStatementPosition = this.scanner.currentPosition - 1;
+ break;
case TokenNamePLUS :
case TokenNameMINUS :
case TokenNameNOT :
case TokenNameTWIDDLE :
+ case TokenNameLBRACE :
this.endPosition = this.scanner.startPosition;
break;
case TokenNamePLUS_PLUS :
@@ -4148,14 +6888,26 @@ protected void consumeToken(int type) {
this.endPosition = this.scanner.startPosition - 1;
//the item is not part of the potential futur expression/statement
break;
- // in order to handle ( expression) ////// (cast)expression///// foo(x)
case TokenNameRPAREN :
+ // in order to handle ( expression) ////// (cast)expression///// foo(x)
this.rParenPos = this.scanner.currentPosition - 1; // position of the end of right parenthesis (in case of unicode \u0029) lex00101
break;
case TokenNameLPAREN :
this.lParenPos = this.scanner.startPosition;
break;
- // case TokenNameQUESTION :
+ case TokenNameAT :
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameQUESTION :
+ pushOnIntStack(this.scanner.startPosition);
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ break;
+ case TokenNameLESS :
+ pushOnIntStack(this.scanner.startPosition);
+ break;
+ case TokenNameELLIPSIS :
+ pushOnIntStack(this.scanner.currentPosition - 1);
+ break;
// case TokenNameCOMMA :
// case TokenNameCOLON :
// case TokenNameEQUAL :
@@ -4198,39 +6950,49 @@ protected void consumeToken(int type) {
// case TokenNameOR :
// case TokenNameDIVIDE :
// case TokenNameGREATER :
- // case TokenNameLESS :
}
}
-protected void consumeTypeDeclarations() {
- // TypeDeclarations ::= TypeDeclarations TypeDeclaration
- concatNodeLists();
+protected void consumeTypeArgument() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
}
-protected void consumeTypeDeclarationsopt() {
- // TypeDeclarationsopt ::= TypeDeclarations
- int length;
- if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
- this.astPtr -= length;
- System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types = new TypeDeclaration[length], 0, length);
- }
+protected void consumeTypeArgumentList() {
+ concatGenericsLists();
}
-protected void consumeTypeImportOnDemandDeclaration() {
- // TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
-
- ImportReference impt = (ImportReference) this.astStack[this.astPtr];
- // flush comments defined prior to import statements
- impt.declarationEnd = this.endStatementPosition;
- impt.declarationSourceEnd =
- this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
+protected void consumeTypeArgumentList1() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentList2() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentList3() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentReferenceType1() {
+ concatGenericsLists();
+ pushOnGenericsStack(getTypeReference(0));
+ intPtr--;
+}
+protected void consumeTypeArgumentReferenceType2() {
+ concatGenericsLists();
+ pushOnGenericsStack(getTypeReference(0));
+ intPtr--;
+}
+protected void consumeTypeArguments() {
+ concatGenericsLists();
+ intPtr--;
- // recovery
- if (this.currentElement != null) {
- this.lastCheckPoint = impt.declarationSourceEnd + 1;
- this.currentElement = this.currentElement.add(impt, 0);
- this.restartRecovery = true;
- this.lastIgnoredToken = -1;
- // used to avoid branching back into the regular automaton
+ if(options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ int length = this.genericsLengthStack[this.genericsLengthPtr];
+ this.problemReporter().invalidUsageOfTypeArguments(
+ (TypeReference)this.genericsStack[this.genericsPtr - length + 1],
+ (TypeReference)this.genericsStack[this.genericsPtr]);
}
}
+protected void consumeTypeDeclarations() {
+ // TypeDeclarations ::= TypeDeclarations TypeDeclaration
+ concatNodeLists();
+}
protected void consumeTypeImportOnDemandDeclarationName() {
// TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
/* push an ImportRef build from the last name
@@ -4251,7 +7013,7 @@ protected void consumeTypeImportOnDemandDeclarationName() {
impt.declarationSourceEnd = impt.sourceEnd;
}
impt.declarationEnd = impt.declarationSourceEnd;
- //endPosition is just before the ;
+ //this.endPosition is just before the ;
impt.declarationSourceStart = this.intStack[this.intPtr--];
// recovery
@@ -4262,6 +7024,93 @@ protected void consumeTypeImportOnDemandDeclarationName() {
this.restartRecovery = true; // used to avoid branching back into the regular automaton
}
}
+protected void consumeTypeParameterHeader() {
+ //TypeParameterHeader ::= Identifier
+ TypeParameter typeParameter = new TypeParameter();
+ long pos = this.identifierPositionStack[this.identifierPtr];
+ final int end = (int) pos;
+ typeParameter.declarationSourceEnd = end;
+ typeParameter.sourceEnd = end;
+ final int start = (int) (pos >>> 32);
+ typeParameter.declarationSourceStart = start;
+ typeParameter.sourceStart = start;
+ typeParameter.name = this.identifierStack[this.identifierPtr--];
+ this.identifierLengthPtr--;
+ pushOnGenericsStack(typeParameter);
+
+ this.listTypeParameterLength++;
+}
+protected void consumeTypeParameter1() {
+ // nothing to do
+}
+protected void consumeTypeParameter1WithExtends() {
+ //TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType1
+ TypeReference superType = (TypeReference) this.genericsStack[this.genericsPtr--];
+ this.genericsLengthPtr--;
+ TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+ typeParameter.declarationSourceEnd = superType.sourceEnd;
+ typeParameter.type = superType;
+ superType.bits |= ASTNode.IsSuperType;
+ this.genericsStack[this.genericsPtr] = typeParameter;
+}
+protected void consumeTypeParameter1WithExtendsAndBounds() {
+ //TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList1
+ int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+ TypeReference[] bounds = new TypeReference[additionalBoundsLength];
+ this.genericsPtr -= additionalBoundsLength;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 0, additionalBoundsLength);
+ TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+ TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+ typeParameter.declarationSourceEnd = bounds[additionalBoundsLength - 1].sourceEnd;
+ typeParameter.type = superType;
+ superType.bits |= ASTNode.IsSuperType;
+ typeParameter.bounds = bounds;
+ for (int i = 0, max = bounds.length; i < max; i++) {
+ bounds[i].bits |= ASTNode.IsSuperType;
+ }
+}
+protected void consumeTypeParameterList() {
+ //TypeParameterList ::= TypeParameterList ',' TypeParameter
+ concatGenericsLists();
+}
+protected void consumeTypeParameterList1() {
+ //TypeParameterList1 ::= TypeParameterList ',' TypeParameter1
+ concatGenericsLists();
+}
+protected void consumeTypeParameters() {
+ intPtr--;
+ if(options.sourceLevel < ClassFileConstants.JDK1_5&&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ int length = this.genericsLengthStack[this.genericsLengthPtr];
+ this.problemReporter().invalidUsageOfTypeParameters(
+ (TypeParameter) this.genericsStack[genericsPtr - length + 1],
+ (TypeParameter) this.genericsStack[genericsPtr]);
+ }
+}
+protected void consumeTypeParameterWithExtends() {
+ //TypeParameter ::= TypeParameterHeader 'extends' ReferenceType
+ TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+ TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+ typeParameter.declarationSourceEnd = superType.sourceEnd;
+ typeParameter.type = superType;
+ superType.bits |= ASTNode.IsSuperType;
+}
+protected void consumeTypeParameterWithExtendsAndBounds() {
+ //TypeParameter ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList
+ int additionalBoundsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+ TypeReference[] bounds = new TypeReference[additionalBoundsLength];
+ this.genericsPtr -= additionalBoundsLength;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, bounds, 0, additionalBoundsLength);
+ TypeReference superType = getTypeReference(this.intStack[this.intPtr--]);
+ TypeParameter typeParameter = (TypeParameter) this.genericsStack[this.genericsPtr];
+ typeParameter.type = superType;
+ superType.bits |= ASTNode.IsSuperType;
+ typeParameter.bounds = bounds;
+ typeParameter.declarationSourceEnd = bounds[additionalBoundsLength - 1].sourceEnd;
+ for (int i = 0, max = bounds.length; i < max; i++) {
+ bounds[i].bits |= ASTNode.IsSuperType;
+ }
+}
protected void consumeUnaryExpression(int op) {
// UnaryExpression ::= '+' PushPosition UnaryExpression
// UnaryExpression ::= '-' PushPosition UnaryExpression
@@ -4275,7 +7124,7 @@ protected void consumeUnaryExpression(int op) {
//is Integer.MAX_VALUE+1.....)
//Same for -9223372036854775808L ............
- //intStack have the position of the operator
+ //this.intStack have the position of the operator
Expression r, exp = this.expressionStack[this.expressionPtr];
if (op == MINUS) {
@@ -4301,7 +7150,7 @@ protected void consumeUnaryExpression(int op, boolean post) {
// ++ and -- operators
//optimize the push/pop
- //intStack has the position of the operator when prefix
+ //this.intStack has the position of the operator when prefix
Expression leftHandSide = this.expressionStack[this.expressionPtr];
if (leftHandSide instanceof Reference) {
@@ -4337,6 +7186,114 @@ protected void consumeVariableInitializers() {
// VariableInitializers ::= VariableInitializers ',' VariableInitializer
concatExpressionLists();
}
+protected void consumeWildcard() {
+ final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+ wildcard.sourceEnd = this.intStack[this.intPtr--];
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard1() {
+ final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+ wildcard.sourceEnd = this.intStack[this.intPtr--];
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard1WithBounds() {
+ // Nothing to do
+ // The wildcard is created by the consumeWildcardBounds1Extends or by consumeWildcardBounds1Super
+}
+protected void consumeWildcard2() {
+ final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+ wildcard.sourceEnd = this.intStack[this.intPtr--];
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard2WithBounds() {
+ // Nothing to do
+ // The wildcard is created by the consumeWildcardBounds2Extends or by consumeWildcardBounds2Super
+}
+protected void consumeWildcard3() {
+ final Wildcard wildcard = new Wildcard(Wildcard.UNBOUND);
+ wildcard.sourceEnd = this.intStack[this.intPtr--];
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcard3WithBounds() {
+ // Nothing to do
+ // The wildcard is created by the consumeWildcardBounds3Extends or by consumeWildcardBounds3Super
+}
+protected void consumeWildcardBounds1Extends() {
+ Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds1Super() {
+ Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ this.intPtr--; // remove the starting position of the super keyword
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds2Extends() {
+ Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds2Super() {
+ Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ this.intPtr--; // remove the starting position of the super keyword
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds3Extends() {
+ Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBounds3Super() {
+ Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+ wildcard.bound = (TypeReference) this.genericsStack[this.genericsPtr];
+ this.intPtr--; // remove the starting position of the super keyword
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ this.genericsStack[this.genericsPtr] = wildcard;
+}
+protected void consumeWildcardBoundsExtends() {
+ Wildcard wildcard = new Wildcard(Wildcard.EXTENDS);
+ wildcard.bound = getTypeReference(this.intStack[this.intPtr--]);
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcardBoundsSuper() {
+ Wildcard wildcard = new Wildcard(Wildcard.SUPER);
+ wildcard.bound = getTypeReference(this.intStack[this.intPtr--]);
+ this.intPtr--; // remove the starting position of the super keyword
+ wildcard.sourceEnd = wildcard.bound.sourceEnd;
+ this.intPtr--; // remove end position of the '?'
+ wildcard.sourceStart = this.intStack[this.intPtr--];
+ pushOnGenericsStack(wildcard);
+}
+protected void consumeWildcardWithBounds() {
+ // Nothing to do
+ // The wildcard is created by the consumeWildcardBoundsExtends or by consumeWildcardBoundsSuper
+}
/**
* Given the current comment stack, answer whether some comment is available in a certain exclusive range
*
@@ -4358,6 +7315,7 @@ public boolean containsComment(int sourceStart, int sourceEnd) {
}
public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
MethodDeclaration m = new MethodDeclaration(compilationResult);
+ m.typeParameters = c.typeParameters;
m.sourceStart = c.sourceStart;
m.sourceEnd = c.sourceEnd;
m.bodyStart = c.bodyStart;
@@ -4367,6 +7325,7 @@ public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, Co
m.selector = c.selector;
m.statements = c.statements;
m.modifiers = c.modifiers;
+ m.annotations = c.annotations;
m.arguments = c.arguments;
m.thrownExceptions = c.thrownExceptions;
m.explicitDeclarations = c.explicitDeclarations;
@@ -4383,7 +7342,16 @@ protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, i
protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
}
-
+protected RecoveredType currentRecoveryType() {
+ if(this.currentElement != null) {
+ if(this.currentElement instanceof RecoveredType) {
+ return (RecoveredType) this.currentElement;
+ } else {
+ return this.currentElement.enclosingType();
+ }
+ }
+ return null;
+}
public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
CompilationUnitDeclaration parsedUnit;
@@ -4398,7 +7366,7 @@ public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, Compila
return parsedUnit;
}
protected void dispatchDeclarationInto(int length) {
- /* they are length on astStack that should go into
+ /* they are length on this.astStack that should go into
methods fields constructors lists of the typeDecl
Return if there is a constructor declaration in the methods declaration */
@@ -4410,32 +7378,38 @@ protected void dispatchDeclarationInto(int length) {
return;
int[] flag = new int[length + 1]; //plus one -- see
int size1 = 0, size2 = 0, size3 = 0;
+ boolean hasAbstractMethods = false;
for (int i = length - 1; i >= 0; i--) {
ASTNode astNode = this.astStack[this.astPtr--];
if (astNode instanceof AbstractMethodDeclaration) {
//methods and constructors have been regrouped into one single list
- flag[i] = 3;
+ flag[i] = 2;
size2++;
- } else {
- if (astNode instanceof TypeDeclaration) {
- flag[i] = 4;
- size3++;
- } else {
- //field
- flag[i] = 1;
- size1++;
+ if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+ hasAbstractMethods = true;
}
+ } else if (astNode instanceof TypeDeclaration) {
+ flag[i] = 3;
+ size3++;
+ } else {
+ //field
+ flag[i] = 1;
+ size1++;
}
}
//arrays creation
TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
- if (size1 != 0)
+ if (size1 != 0) {
typeDecl.fields = new FieldDeclaration[size1];
- if (size2 != 0)
+ }
+ if (size2 != 0) {
typeDecl.methods = new AbstractMethodDeclaration[size2];
- if (size3 != 0)
+ if (hasAbstractMethods) typeDecl.bits |= ASTNode.HasAbstractMethods;
+ }
+ if (size3 != 0) {
typeDecl.memberTypes = new TypeDeclaration[size3];
+ }
//arrays fill up
size1 = size2 = size3 = 0;
@@ -4455,7 +7429,7 @@ protected void dispatchDeclarationInto(int length) {
size1 - length2,
length2);
break;
- case 3 :
+ case 2 :
size2 += (length2 = end - start);
System.arraycopy(
this.astStack,
@@ -4464,7 +7438,7 @@ protected void dispatchDeclarationInto(int length) {
size2 - length2,
length2);
break;
- case 4 :
+ case 3 :
size3 += (length2 = end - start);
System.arraycopy(
this.astStack,
@@ -4484,6 +7458,95 @@ protected void dispatchDeclarationInto(int length) {
}
}
}
+protected void dispatchDeclarationIntoEnumDeclaration(int length) {
+
+ if (length == 0)
+ return;
+ int[] flag = new int[length + 1]; //plus one -- see
+ int size1 = 0, size2 = 0, size3 = 0;
+ TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr - length];
+ boolean hasAbstractMethods = false;
+ for (int i = length - 1; i >= 0; i--) {
+ ASTNode astNode = this.astStack[this.astPtr--];
+ if (astNode instanceof AbstractMethodDeclaration) {
+ //methods and constructors have been regrouped into one single list
+ flag[i] = 2;
+ size2++;
+ if (((AbstractMethodDeclaration) astNode).isAbstract()) {
+ hasAbstractMethods = true;
+ }
+ } else if (astNode instanceof TypeDeclaration) {
+ flag[i] = 3;
+ size3++;
+ } else if (astNode instanceof FieldDeclaration) {
+ flag[i] = 1;
+ size1++;
+// if(astNode instanceof EnumConstant) {
+// EnumConstant constant = (EnumConstant) astNode;
+// ((AllocationExpression)constant.initialization).type = new SingleTypeReference(enumDeclaration.name,
+// (((long) enumDeclaration.sourceStart) << 32) + enumDeclaration.sourceEnd);
+// }
+ }
+ }
+
+ //arrays creation
+ if (size1 != 0) {
+ enumDeclaration.fields = new FieldDeclaration[size1];
+ }
+ if (size2 != 0) {
+ enumDeclaration.methods = new AbstractMethodDeclaration[size2];
+ if (hasAbstractMethods) enumDeclaration.bits |= ASTNode.HasAbstractMethods;
+ }
+ if (size3 != 0) {
+ enumDeclaration.memberTypes = new TypeDeclaration[size3];
+ }
+
+ //arrays fill up
+ size1 = size2 = size3 = 0;
+ int flagI = flag[0], start = 0;
+ int length2;
+ for (int end = 0; end <= length; end++) // the plus one allows to
+ {
+ if (flagI != flag[end]) //treat the last element as a ended flag.....
+ { //array copy
+ switch (flagI) {
+ case 1 :
+ size1 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.fields,
+ size1 - length2,
+ length2);
+ break;
+ case 2 :
+ size2 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.methods,
+ size2 - length2,
+ length2);
+ break;
+ case 3 :
+ size3 += (length2 = end - start);
+ System.arraycopy(
+ this.astStack,
+ this.astPtr + start + 1,
+ enumDeclaration.memberTypes,
+ size3 - length2,
+ length2);
+ break;
+ }
+ flagI = flag[start = end];
+ }
+ }
+
+ if (enumDeclaration.memberTypes != null) {
+ for (int i = enumDeclaration.memberTypes.length - 1; i >= 0; i--) {
+ enumDeclaration.memberTypes[i].enclosingType = enumDeclaration;
+ }
+ }}
protected CompilationUnitDeclaration endParse(int act) {
this.lastAct = act;
@@ -4569,7 +7632,7 @@ public int flushCommentsDefinedPriorTo(int position) {
this.scanner.commentPtr = validCount - 1;
return position;
}
-public final int getFirstToken() {
+public int getFirstToken() {
// the first token is a virtual token that
// allows the parser to parse several goals
// even if they aren't LALR(1)....
@@ -4642,20 +7705,17 @@ public int[] getJavaDocPositions() {
if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
return; //work already done ...
- //real parse of the method....
- char[] contents = unit.compilationResult.compilationUnit.getContents();
- this.scanner.setSource(contents);
-
// save existing values to restore them at the end of the parsing process
// see bug 47079 for more details
int[] oldLineEnds = this.scanner.lineEnds;
int oldLinePtr = this.scanner.linePtr;
- final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
- this.scanner.lineEnds = lineSeparatorPositions;
- this.scanner.linePtr = lineSeparatorPositions.length - 1;
-
+ //real parse of the method....
+ CompilationResult compilationResult = unit.compilationResult;
+ this.scanner.setSource(compilationResult);
+
if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+ char[] contents = compilationResult.compilationUnit.getContents();
this.javadocParser.scanner.setSource(contents);
}
if (unit.types != null) {
@@ -4671,37 +7731,69 @@ public int[] getJavaDocPositions() {
this.scanner.lineEnds = oldLineEnds;
this.scanner.linePtr = oldLinePtr;
}
-protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
-This variable is a type reference and dim will be its dimensions*/
+protected char getNextCharacter(char[] comment, int[] index) {
+ char nextCharacter = comment[index[0]++];
+ switch(nextCharacter) {
+ case '\\' :
+ int c1, c2, c3, c4;
+ index[0]++;
+ while (comment[index[0]] == 'u') index[0]++;
+ if (!(((c1 = Character.getNumericValue(comment[index[0]++])) > 15
+ || c1 < 0)
+ || ((c2 = Character.getNumericValue(comment[index[0]++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(comment[index[0]++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(comment[index[0]++])) > 15 || c4 < 0))) {
+ nextCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ break;
+ }
+ return nextCharacter;
+}
+protected Expression getTypeReference(Expression exp) {
+
+ exp.bits &= ~ASTNode.RestrictiveFlagMASK;
+ exp.bits |= Binding.TYPE;
+ return exp;
+}
+protected TypeReference getTypeReference(int dim) {
+ /* build a Reference on a variable that may be qualified or not
+ This variable is a type reference and dim will be its dimensions*/
- int length;
TypeReference ref;
- if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
- // single variable reference
+ int length = this.identifierLengthStack[this.identifierLengthPtr--];
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = this.intStack[this.intPtr--];
if (dim == 0) {
- ref =
- new SingleTypeReference(
- this.identifierStack[this.identifierPtr],
- this.identifierPositionStack[this.identifierPtr--]);
+ ref.sourceEnd = this.intStack[this.intPtr--];
} else {
- ref =
- new ArrayTypeReference(
- this.identifierStack[this.identifierPtr],
- dim,
- this.identifierPositionStack[this.identifierPtr--]);
- ref.sourceEnd = this.endPosition;
+ this.intPtr--;
+ ref.sourceEnd = this.endPosition;
}
} else {
- if (length < 0) { //flag for precompiled type reference on base types
- ref = TypeReference.baseTypeReference(-length, dim);
- ref.sourceStart = this.intStack[this.intPtr--];
+ int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
+ if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
+ // generic type
+ ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
+ } else if (length == 1) {
+ // single variable reference
+ this.genericsLengthPtr--; // pop the 0
if (dim == 0) {
- ref.sourceEnd = this.intStack[this.intPtr--];
+ ref =
+ new SingleTypeReference(
+ this.identifierStack[this.identifierPtr],
+ this.identifierPositionStack[this.identifierPtr--]);
} else {
- this.intPtr--;
- ref.sourceEnd = this.endPosition;
+ ref =
+ new ArrayTypeReference(
+ this.identifierStack[this.identifierPtr],
+ dim,
+ this.identifierPositionStack[this.identifierPtr--]);
+ ref.sourceEnd = this.endPosition;
}
- } else { //Qualified variable reference
+ } else {
+ this.genericsLengthPtr--;
+ //Qualified variable reference
char[][] tokens = new char[length][];
this.identifierPtr -= length;
long[] positions = new long[length];
@@ -4722,11 +7814,48 @@ This variable is a type reference and dim will be its dimensions*/
}
return ref;
}
-protected Expression getTypeReference(Expression exp) {
-
- exp.bits &= ~ASTNode.RestrictiveFlagMASK;
- exp.bits |= TYPE;
- return exp;
+protected TypeReference getTypeReferenceForGenericType(int dim, int identifierLength, int numberOfIdentifiers) {
+ if (identifierLength == 1 && numberOfIdentifiers == 1) {
+ int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+ TypeReference[] typeArguments = new TypeReference[currentTypeArgumentsLength];
+ this.genericsPtr -= currentTypeArgumentsLength;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments, 0, currentTypeArgumentsLength);
+ ParameterizedSingleTypeReference parameterizedSingleTypeReference = new ParameterizedSingleTypeReference(this.identifierStack[this.identifierPtr], typeArguments, dim, this.identifierPositionStack[this.identifierPtr--]);
+ if (dim != 0) {
+ parameterizedSingleTypeReference.sourceEnd = this.endPosition;
+ }
+ return parameterizedSingleTypeReference;
+ } else {
+ TypeReference[][] typeArguments = new TypeReference[numberOfIdentifiers][];
+ char[][] tokens = new char[numberOfIdentifiers][];
+ long[] positions = new long[numberOfIdentifiers];
+ int index = numberOfIdentifiers;
+ int currentIdentifiersLength = identifierLength;
+ while (index > 0) {
+ int currentTypeArgumentsLength = this.genericsLengthStack[this.genericsLengthPtr--];
+ if (currentTypeArgumentsLength != 0) {
+ this.genericsPtr -= currentTypeArgumentsLength;
+ System.arraycopy(this.genericsStack, this.genericsPtr + 1, typeArguments[index - 1] = new TypeReference[currentTypeArgumentsLength], 0, currentTypeArgumentsLength);
+ }
+ switch(currentIdentifiersLength) {
+ case 1 :
+ // we are in a case A.C or A.C
+ tokens[index - 1] = this.identifierStack[this.identifierPtr];
+ positions[index - 1] = this.identifierPositionStack[this.identifierPtr--];
+ break;
+ default:
+ // we are in a case A.B.C.C or A.B.C...
+ this.identifierPtr -= currentIdentifiersLength;
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, index - currentIdentifiersLength, currentIdentifiersLength);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, index - currentIdentifiersLength, currentIdentifiersLength);
+ }
+ index -= currentIdentifiersLength;
+ if (index > 0) {
+ currentIdentifiersLength = this.identifierLengthStack[this.identifierLengthPtr--];
+ }
+ }
+ return new ParameterizedQualifiedTypeReference(tokens, typeArguments, dim, positions);
+ }
}
protected NameReference getUnspecifiedReference() {
/* build a (unspecified) NameReference which may be qualified*/
@@ -4772,7 +7901,7 @@ protected NameReference getUnspecifiedReferenceOptimized() {
this.identifierStack[this.identifierPtr],
this.identifierPositionStack[this.identifierPtr--]);
ref.bits &= ~ASTNode.RestrictiveFlagMASK;
- ref.bits |= LOCAL | FIELD;
+ ref.bits |= Binding.LOCAL | Binding.FIELD;
return ref;
}
@@ -4793,7 +7922,7 @@ protected NameReference getUnspecifiedReferenceOptimized() {
(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
(int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
ref.bits &= ~ASTNode.RestrictiveFlagMASK;
- ref.bits |= LOCAL | FIELD;
+ ref.bits |= Binding.LOCAL | Binding.FIELD;
return ref;
}
public void goForBlockStatementsopt() {
@@ -4818,7 +7947,6 @@ public void goForCompilationUnit(){
//tells the scanner to go for compilation unit parsing
this.firstToken = TokenNamePLUS_PLUS ;
- this.scanner.linePtr = -1;
this.scanner.foundTaskCount = 0;
this.scanner.recordLineSeparator = true;
this.scanner.currentLine= null;
@@ -4843,8 +7971,12 @@ public void goForGenericMethodDeclaration(){
}
public void goForHeaders(){
//tells the scanner to go for headers only parsing
-
- this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+ RecoveredType currentType = this.currentRecoveryType();
+ if(currentType != null && currentType.insideEnumConstantPart) {
+ this.firstToken = TokenNameNOT;
+ } else {
+ this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+ }
this.scanner.recordLineSeparator = true; // recovery goals must record line separators
}
public void goForImportDeclaration(){
@@ -4859,6 +7991,12 @@ public void goForInitializer(){
this.firstToken = TokenNameRIGHT_SHIFT ;
this.scanner.recordLineSeparator = false;
}
+public void goForMemberValue() {
+ //tells the scanner to go for a memeber value parsing
+
+ this.firstToken = TokenNameOR_OR;
+ this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+}
public void goForMethodBody(){
//tells the scanner to go for method body parsing
@@ -4918,11 +8056,11 @@ protected void ignoreInvalidConstructorDeclaration(boolean hasBody) {
// InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false
/*
- astStack : modifiers arguments throws statements
- identifierStack : name
+ this.astStack : modifiers arguments throws statements
+ this.identifierStack : name
==>
- astStack : MethodDeclaration
- identifierStack :
+ this.astStack : MethodDeclaration
+ this.identifierStack :
*/
if (hasBody) {
// pop the position of the { (body of the method) pushed in block decl
@@ -4949,13 +8087,13 @@ protected void ignoreMethodBody() {
// InterfaceMemberDeclaration ::= InvalidMethodDeclaration
/*
- astStack : modifiers arguments throws statements
- identifierStack : type name
- intStack : dim dim dim
+ this.astStack : modifiers arguments throws statements
+ this.identifierStack : type name
+ this.intStack : dim dim dim
==>
- astStack : MethodDeclaration
- identifierStack :
- intStack :
+ this.astStack : MethodDeclaration
+ this.identifierStack :
+ this.intStack :
*/
// pop the position of the { (body of the method) pushed in block decl
@@ -5013,7 +8151,7 @@ public void initialize() {
}
System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
- // reset scanner state
+ // reset this.scanner state
this.scanner.commentPtr = -1;
this.scanner.foundTaskCount = 0;
this.scanner.eofPosition = Integer.MAX_VALUE;
@@ -5031,11 +8169,18 @@ public void initialize() {
this.recoveredStaticInitializerStart = 0;
this.lastIgnoredToken = -1;
this.lastErrorEndPosition = -1;
+ this.lastErrorEndPositionBeforeRecovery = -1;
+ this.lastJavadocEnd = -1;
this.listLength = 0;
+ this.listTypeParameterLength = 0;
this.rBraceStart = 0;
this.rBraceEnd = 0;
this.rBraceSuccessorStart = 0;
+
+ this.genericsIdentifiersLengthPtr = -1;
+ this.genericsLengthPtr = -1;
+ this.genericsPtr = -1;
}
public void initializeScanner(){
this.scanner = new Scanner(
@@ -5047,45 +8192,7 @@ public void initializeScanner(){
this.options.taskPriorites/*taskPriorities*/,
this.options.isTaskCaseSensitive/*taskCaseSensitive*/);
}
-public final static void initTables() throws java.io.IOException {
-
- final String prefix = FILEPREFIX;
- int i = 0;
- lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- char[] chars = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- check_table = new short[chars.length];
- for (int c = chars.length; c-- > 0;) {
- check_table[c] = (short) (chars[c] - 32768);
- }
- asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-
- scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-
- rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-
- name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
- readableName = readReadableNameTable(READABLE_NAMES);
-
- base_action = lhs;
-}
-public static int in_symbol(int state) {
- return in_symb[original_state(state)];
-}
-public final void jumpOverMethodBody() {
+public void jumpOverMethodBody() {
//on diet parsing.....do not buffer method statements
//the scanner.diet is reinitialized to false
@@ -5130,7 +8237,7 @@ protected void markInitializersWithLocalType(TypeDeclaration type) {
protected boolean moveRecoveryCheckpoint() {
int pos = this.lastCheckPoint;
- /* reset scanner, and move checkpoint by one token */
+ /* reset this.scanner, and move checkpoint by one token */
this.scanner.startPosition = pos;
this.scanner.currentPosition = pos;
this.scanner.diet = false; // quit jumping over method bodies
@@ -5166,7 +8273,7 @@ protected boolean moveRecoveryCheckpoint() {
}
this.lastCheckPoint = this.scanner.currentPosition;
- /* reset scanner again to previous checkpoint location*/
+ /* reset this.scanner again to previous checkpoint location*/
this.scanner.startPosition = pos;
this.scanner.currentPosition = pos;
this.scanner.commentPtr = -1;
@@ -5179,7 +8286,7 @@ protected boolean moveRecoveryCheckpoint() {
The following implementation moves the checkpoint location by one line:
int pos = this.lastCheckPoint;
- // reset scanner, and move checkpoint by one token
+ // reset this.scanner, and move checkpoint by one token
this.scanner.startPosition = pos;
this.scanner.currentPosition = pos;
this.scanner.diet = false; // quit jumping over method bodies
@@ -5234,7 +8341,7 @@ protected boolean moveRecoveryCheckpoint() {
}
this.lastCheckPoint = this.scanner.currentPosition;
- // reset scanner again to previous checkpoint location
+ // reset this.scanner again to previous checkpoint location
this.scanner.startPosition = pos;
this.scanner.currentPosition = pos;
this.scanner.commentPtr = -1;
@@ -5259,35 +8366,40 @@ protected MessageSend newMessageSend() {
}
return m;
}
-public static int nasi(int state) {
- return nasb[original_state(state)];
-}
-public static int ntAction(int state, int sym) {
- return base_action[state + sym];
+protected MessageSend newMessageSendWithTypeArguments() {
+ MessageSend m = new MessageSend();
+ int length;
+ if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+ this.expressionPtr -= length;
+ System.arraycopy(
+ this.expressionStack,
+ this.expressionPtr + 1,
+ m.arguments = new Expression[length],
+ 0,
+ length);
+ }
+ return m;
}
-private final void optimizedConcatNodeLists() {
+protected void optimizedConcatNodeLists() {
/*back from a recursive loop. Virtualy group the
- astNode into an array using astLengthStack*/
+ astNode into an array using this.astLengthStack*/
/*
- * This is a case where you have two sublists into the astStack that you want
- * to merge in one list. There is no action required on the astStack. The only
+ * This is a case where you have two sublists into the this.astStack that you want
+ * to merge in one list. There is no action required on the this.astStack. The only
* thing you need to do is merge the two lengths specified on the astStackLength.
* The top two length are for example:
* ... p n
* and you want to result in a list like:
* ... n+p
* This means that the p could be equals to 0 in case there is no astNode pushed
- * on the astStack.
+ * on the this.astStack.
* Look at the InterfaceMemberDeclarations for an example.
* This case optimizes the fact that p == 1.
*/
this.astLengthStack[--this.astLengthPtr]++;
}
-protected static int original_state(int state) {
- return -base_check(state);
-}
/*main loop of the automat
When a rule is reduced, the method consumeRule(int) is called with the number
of the consumed rule. When a terminal is consumed, the method consumeToken(int) is
@@ -5295,6 +8407,7 @@ called in order to remember (when needed) the consumed token */
// (int)asr[asi(act)]
// name[symbol_index[currentKind]]
protected void parse() {
+ if (DEBUG) System.out.println("-- ENTER INSIDE PARSE METHOD --"); //$NON-NLS-1$
boolean isDietParse = this.diet;
int oldFirstToken = getFirstToken();
this.hasError = false;
@@ -5314,10 +8427,9 @@ protected void parse() {
this.stack[this.stateStackTop] = act;
act = tAction(act, this.currentToken);
-
if (act == ERROR_ACTION || this.restartRecovery) {
int errorPos = this.scanner.currentPosition;
- if (!this.hasReportedError){
+ if (!this.hasReportedError) {
this.hasError = true;
}
if (resumeOnSyntaxError()) {
@@ -5332,7 +8444,7 @@ protected void parse() {
}
if (act <= NUM_RULES) {
this.stateStackTop--;
-
+
} else if (act > ERROR_ACTION) { /* shift-reduce */
consumeToken(this.currentToken);
if (this.currentElement != null) this.recoveryTokenCheck();
@@ -5366,6 +8478,7 @@ protected void parse() {
}
break ProcessTerminals;
}
+
ProcessNonTerminals : do { /* reduce */
consumeRule(act);
this.stateStackTop -= (rhs[act] - 1);
@@ -5377,68 +8490,7 @@ protected void parse() {
if (this.reportSyntaxErrorIsRequired && this.hasError) {
reportSyntaxErrors(isDietParse, oldFirstToken);
}
-}
-// A P I
-protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
- if(this.referenceContext instanceof MethodDeclaration) {
- MethodDeclaration methodDeclaration = (MethodDeclaration) this.referenceContext;
- if(methodDeclaration.errorInSignature){
- return;
- }
- }
- this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
- this.scanner.recordLineSeparator = false;
-
- int start = this.scanner.initialPosition;
- int end = this.scanner.eofPosition <= Integer.MAX_VALUE ? this.scanner.eofPosition - 1 : this.scanner.eofPosition;
- if(isDietParse) {
- TypeDeclaration[] types = this.compilationUnit.types;
-
- int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
- DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2]);
- diagnoseParser.diagnoseParse();
-
- reportSyntaxErrorsForSkippedMethod(types);
- this.scanner.resetTo(start, end);
- } else {
- DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end);
- diagnoseParser.diagnoseParse();
- }
-}
-private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){
- if(types != null) {
- for (int i = 0; i < types.length; i++) {
- TypeDeclaration[] memberTypes = types[i].memberTypes;
- if(memberTypes != null) {
- reportSyntaxErrorsForSkippedMethod(memberTypes);
- }
-
- AbstractMethodDeclaration[] methods = types[i].methods;
- if(methods != null) {
- for (int j = 0; j < methods.length; j++) {
- AbstractMethodDeclaration method = methods[j];
- if(methods[j].errorInSignature) {
- DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd);
- diagnoseParser.diagnoseParse();
- }
- }
- }
-
- FieldDeclaration[] fields = types[i].fields;
- if (fields != null) {
- int length = fields.length;
- for (int j = 0; j < length; j++) {
- if (fields[j] instanceof Initializer) {
- Initializer initializer = (Initializer)fields[j];
- if(initializer.errorInSignature){
- DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd);
- diagnoseParser.diagnoseParse();
- }
- }
- }
- }
- }
- }
+ if (DEBUG) System.out.println("-- EXIT FROM PARSE METHOD --"); //$NON-NLS-1$
}
public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
parse(cd, unit, false);
@@ -5553,6 +8605,57 @@ public void parse(
}
// A P I
+public CompilationUnitDeclaration parse(
+ ICompilationUnit sourceUnit,
+ CompilationResult compilationResult) {
+ // parses a compilation unit and manages error handling (even bugs....)
+
+ return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
+}
+// A P I
+
+public CompilationUnitDeclaration parse(
+ ICompilationUnit sourceUnit,
+ CompilationResult compilationResult,
+ int start,
+ int end) {
+ // parses a compilation unit and manages error handling (even bugs....)
+
+ CompilationUnitDeclaration unit;
+ try {
+ /* automaton initialization */
+ initialize();
+ goForCompilationUnit();
+
+ /* scanners initialization */
+ char[] contents = sourceUnit.getContents();
+ this.scanner.setSource(contents);
+ if (end != -1) this.scanner.resetTo(start, end);
+ if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+ this.javadocParser.scanner.setSource(contents);
+ if (end != -1) {
+ this.javadocParser.scanner.resetTo(start, end);
+ }
+ }
+ /* unit creation */
+ this.referenceContext =
+ this.compilationUnit =
+ new CompilationUnitDeclaration(
+ this.problemReporter,
+ compilationResult,
+ this.scanner.source.length);
+ /* run automaton */
+ parse();
+ } finally {
+ unit = this.compilationUnit;
+ this.compilationUnit = null; // reset parser
+ // tag unit has having read bodies
+ if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;
+ }
+ return unit;
+}
+// A P I
+
public void parse(
Initializer initializer,
TypeDeclaration type,
@@ -5619,94 +8722,43 @@ public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
initialize();
goForBlockStatementsopt();
- this.nestedMethod[this.nestedType]++;
- pushOnRealBlockStack(0);
-
- this.referenceContext = md;
- this.compilationUnit = unit;
-
- this.scanner.resetTo(md.bodyStart, md.bodyEnd);
- // reset the scanner to parser from { down to }
- try {
- parse();
- } catch (AbortCompilation ex) {
- this.lastAct = ERROR_ACTION;
- } finally {
- this.nestedMethod[this.nestedType]--;
- }
-
- checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
-
- if (this.lastAct == ERROR_ACTION) {
- return;
- }
-
- //refill statements
- md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
- int length;
- if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
- System.arraycopy(
- this.astStack,
- (this.astPtr -= length) + 1,
- md.statements = new Statement[length],
- 0,
- length);
- } else {
- if (!containsComment(md.bodyStart, md.bodyEnd)) {
- md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
- }
- }
-}
-// A P I
-
-public CompilationUnitDeclaration parse(
- ICompilationUnit sourceUnit,
- CompilationResult compilationResult) {
- // parses a compilation unit and manages error handling (even bugs....)
-
- return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
-}
-// A P I
-
-public CompilationUnitDeclaration parse(
- ICompilationUnit sourceUnit,
- CompilationResult compilationResult,
- int start,
- int end) {
- // parses a compilation unit and manages error handling (even bugs....)
-
- CompilationUnitDeclaration unit;
- try {
- /* automaton initialization */
- initialize();
- goForCompilationUnit();
-
- /* scanners initialization */
- char[] contents = sourceUnit.getContents();
- this.scanner.setSource(contents);
- if (end != -1) this.scanner.resetTo(start, end);
- if (this.javadocParser != null && this.javadocParser.checkDocComment) {
- this.javadocParser.scanner.setSource(contents);
- if (end != -1) {
- this.javadocParser.scanner.resetTo(start, end);
- }
- }
- /* unit creation */
- this.referenceContext =
- this.compilationUnit =
- new CompilationUnitDeclaration(
- this.problemReporter,
- compilationResult,
- this.scanner.source.length);
- /* run automaton */
+ this.nestedMethod[this.nestedType]++;
+ pushOnRealBlockStack(0);
+
+ this.referenceContext = md;
+ this.compilationUnit = unit;
+
+ this.scanner.resetTo(md.bodyStart, md.bodyEnd);
+ // reset the scanner to parser from { down to }
+ try {
parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
} finally {
- unit = this.compilationUnit;
- this.compilationUnit = null; // reset parser
- // tag unit has having read bodies
- if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
+
+ if (this.lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ //refill statements
+ md.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+ int length;
+ if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+ System.arraycopy(
+ this.astStack,
+ (this.astPtr -= length) + 1,
+ md.statements = new Statement[length],
+ 0,
+ length);
+ } else {
+ if (!containsComment(md.bodyStart, md.bodyEnd)) {
+ md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+ }
}
- return unit;
}
public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
/* automaton initialization */
@@ -5771,6 +8823,31 @@ public Expression parseExpression(char[] source, int offset, int length, Compila
return this.expressionStack[this.expressionPtr];
}
+public Expression parseMemberValue(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+
+ initialize();
+ goForMemberValue();
+ this.nestedMethod[this.nestedType]++;
+
+ this.referenceContext = unit;
+ this.compilationUnit = unit;
+
+ this.scanner.setSource(source);
+ this.scanner.resetTo(offset, offset + length - 1);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ this.lastAct = ERROR_ACTION;
+ } finally {
+ this.nestedMethod[this.nestedType]--;
+ }
+
+ if (this.lastAct == ERROR_ACTION) {
+ return null;
+ }
+
+ return this.expressionStack[this.expressionPtr];
+}
public void persistLineSeparatorPositions() {
if (this.scanner.recordLineSeparator) {
this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
@@ -5899,6 +8976,48 @@ protected void pushOnExpressionStackLengthStack(int pos) {
}
this.expressionLengthStack[this.expressionLengthPtr] = pos;
}
+protected void pushOnGenericsStack(ASTNode node) {
+ /*add a new obj on top of the generics stack
+ genericsPtr points on the top*/
+
+ int stackLength = this.genericsStack.length;
+ if (++this.genericsPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsStack, 0,
+ this.genericsStack = new ASTNode[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsStack[this.genericsPtr] = node;
+
+ stackLength = this.genericsLengthStack.length;
+ if (++this.genericsLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsLengthStack, 0,
+ this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsLengthStack[this.genericsLengthPtr] = 1;
+}
+protected void pushOnGenericsIdentifiersLengthStack(int pos) {
+ int stackLength = this.genericsIdentifiersLengthStack.length;
+ if (++this.genericsIdentifiersLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsIdentifiersLengthStack, 0,
+ this.genericsIdentifiersLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr] = pos;
+}
+protected void pushOnGenericsLengthStack(int pos) {
+ int stackLength = this.genericsLengthStack.length;
+ if (++this.genericsLengthPtr >= stackLength) {
+ System.arraycopy(
+ this.genericsLengthStack, 0,
+ this.genericsLengthStack = new int[stackLength + GenericsStackIncrement], 0,
+ stackLength);
+ }
+ this.genericsLengthStack[this.genericsLengthPtr] = pos;
+}
protected void pushOnIntStack(int pos) {
int stackLength = this.intStack.length;
@@ -5921,104 +9040,6 @@ protected void pushOnRealBlockStack(int i){
}
this.realBlockStack[this.realBlockPtr] = i;
}
-protected static char[] readTable(String filename) throws java.io.IOException {
-
- //files are located at Parser.class directory
-
- InputStream stream = Parser.class.getResourceAsStream(filename);
- if (stream == null) {
- throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
- }
- byte[] bytes = null;
- try {
- stream = new BufferedInputStream(stream);
- bytes = Util.getInputStreamAsByteArray(stream, -1);
- } finally {
- try {
- stream.close();
- } catch (IOException e) {
- // ignore
- }
- }
-
- //minimal integrity check (even size expected)
- int length = bytes.length;
- if (length % 2 != 0)
- throw new java.io.IOException(Util.bind("parser.corruptedFile",filename)); //$NON-NLS-1$
-
- // convert bytes into chars
- char[] chars = new char[length / 2];
- int i = 0;
- int charIndex = 0;
-
- while (true) {
- chars[charIndex++] = (char) (((bytes[i++] & 0xFF) << 8) + (bytes[i++] & 0xFF));
- if (i == length)
- break;
- }
- return chars;
-}
-protected static byte[] readByteTable(String filename) throws java.io.IOException {
-
- //files are located at Parser.class directory
-
- InputStream stream = Parser.class.getResourceAsStream(filename);
- if (stream == null) {
- throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
- }
- byte[] bytes = null;
- try {
- stream = new BufferedInputStream(stream);
- bytes = Util.getInputStreamAsByteArray(stream, -1);
- } finally {
- try {
- stream.close();
- } catch (IOException e) {
- // ignore
- }
- }
- return bytes;
-}
-protected static String[] readReadableNameTable(String filename) {
- String[] result = new String[name.length];
-
- ResourceBundle bundle;
- try {
- bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
- } catch(MissingResourceException e) {
- System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
- throw e;
- }
- for (int i = 0; i < NT_OFFSET + 1; i++) {
- result[i] = name[i];
- }
- for (int i = NT_OFFSET; i < name.length; i++) {
- try {
- String n = bundle.getString(name[i]);
- if(n != null && n.length() > 0) {
- result[i] = n;
- } else {
- result[i] = name[i];
- }
- } catch(MissingResourceException e) {
- result[i] = name[i];
- }
- }
- return result;
-}
-
-protected static String[] readNameTable(String filename) throws java.io.IOException {
- char[] contents = readTable(filename);
- char[][] nameAsChar = CharOperation.splitOn('\n', contents);
-
- String[] result = new String[nameAsChar.length + 1];
- result[0] = null;
- for (int i = 0; i < nameAsChar.length; i++) {
- result[i + 1] = new String(nameAsChar[i]);
- }
-
- return result;
-}
public void recoveryExitFromVariable() {
if(this.currentElement != null && this.currentElement.parent != null) {
if(this.currentElement instanceof RecoveredLocalVariable) {
@@ -6061,11 +9082,20 @@ public void recoveryTokenCheck() {
this.lastCheckPoint = this.scanner.currentPosition;
if (newElement != this.currentElement){
this.currentElement = newElement;
+// if (newElement instanceof RecoveredField && this.dietInt <= 0) {
+// if (((RecoveredField)newElement).fieldDeclaration.type == null) { // enum constant
+// this.isInsideEnumConstantPart = true; // restore status
+// }
+// }
}
break;
case TokenNameSEMICOLON :
this.endStatementPosition = this.scanner.currentPosition - 1;
this.endPosition = this.scanner.startPosition - 1;
+ RecoveredType currentType = this.currentRecoveryType();
+ if(currentType != null) {
+ currentType.insideEnumConstantPart = false;
+ }
// fall through
default : {
if (this.rBraceEnd > this.rBraceSuccessorStart && this.scanner.currentPosition != this.scanner.startPosition){
@@ -6076,6 +9106,74 @@ public void recoveryTokenCheck() {
}
this.ignoreNextOpeningBrace = false;
}
+// A P I
+protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
+ if(this.referenceContext instanceof MethodDeclaration) {
+ MethodDeclaration methodDeclaration = (MethodDeclaration) this.referenceContext;
+ if(methodDeclaration.errorInSignature){
+ return;
+ }
+ }
+ this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+ this.scanner.recordLineSeparator = false;
+
+ int start = this.scanner.initialPosition;
+ int end = this.scanner.eofPosition <= Integer.MAX_VALUE ? this.scanner.eofPosition - 1 : this.scanner.eofPosition;
+ if(isDietParse) {
+ TypeDeclaration[] types = this.compilationUnit.types;
+
+ int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2], this.options);
+ diagnoseParser.diagnoseParse();
+
+ reportSyntaxErrorsForSkippedMethod(types);
+ this.scanner.resetTo(start, end);
+ } else {
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, this.options);
+ diagnoseParser.diagnoseParse();
+ }
+}
+private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){
+ if(types != null) {
+ for (int i = 0; i < types.length; i++) {
+ TypeDeclaration[] memberTypes = types[i].memberTypes;
+ if(memberTypes != null) {
+ reportSyntaxErrorsForSkippedMethod(memberTypes);
+ }
+
+ AbstractMethodDeclaration[] methods = types[i].methods;
+ if(methods != null) {
+ for (int j = 0; j < methods.length; j++) {
+ AbstractMethodDeclaration method = methods[j];
+ if(method.errorInSignature) {
+ if(method.isAnnotationMethod()) {
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameQUESTION, method.declarationSourceStart, method.declarationSourceEnd, this.options);
+ diagnoseParser.diagnoseParse();
+ } else {
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd, this.options);
+ diagnoseParser.diagnoseParse();
+ }
+
+ }
+ }
+ }
+
+ FieldDeclaration[] fields = types[i].fields;
+ if (fields != null) {
+ int length = fields.length;
+ for (int j = 0; j < length; j++) {
+ if (fields[j] instanceof Initializer) {
+ Initializer initializer = (Initializer)fields[j];
+ if(initializer.errorInSignature){
+ DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd, this.options);
+ diagnoseParser.diagnoseParse();
+ }
+ }
+ }
+ }
+ }
+ }
+}
protected void resetModifiers() {
this.modifiers = AccDefault;
this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
@@ -6099,8 +9197,13 @@ protected void resetStacks() {
this.realBlockStack[this.realBlockPtr = 0] = 0;
this.recoveredStaticInitializerStart = 0;
this.listLength = 0;
+ this.listTypeParameterLength = 0;
// Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=29365
if (this.scanner != null) this.scanner.currentLine = null;
+
+ this.genericsIdentifiersLengthPtr = -1;
+ this.genericsLengthPtr = -1;
+ this.genericsPtr = -1;
}
/*
* Reset context so as to resume to regular parse loop
@@ -6111,11 +9214,9 @@ protected void resetStacks() {
*/
protected boolean resumeAfterRecovery() {
- // Reset javadoc before restart parsing after recovery
- this.javadoc = null;
-
// reset internal stacks
this.resetStacks();
+ this.resetModifiers();
/* attempt to move checkpoint location */
if (!this.moveRecoveryCheckpoint()) {
@@ -6131,16 +9232,15 @@ protected boolean resumeAfterRecovery() {
// does not know how to restart
return false;
}
-/*
- * Syntax error was detected. Will attempt to perform some recovery action in order
- * to resume to the regular parse loop.
- */
protected boolean resumeOnSyntaxError() {
/* request recovery initialization */
if (this.currentElement == null){
- this.currentElement =
- this.buildInitialRecoveryState(); // build some recovered elements
+ // Reset javadoc before restart parsing after recovery
+ this.javadoc = null;
+
+ // build some recovered elements
+ this.currentElement = buildInitialRecoveryState();
}
/* do not investigate deeper in recovery when no recovered element */
if (this.currentElement == null) return false;
@@ -6155,43 +9255,56 @@ protected boolean resumeOnSyntaxError() {
/* attempt to reset state in order to resume to parse loop */
return this.resumeAfterRecovery();
}
-public static int tAction(int state, int sym) {
- return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
-}
public String toString() {
- String s = "identifierStack : char[][] = {"; //$NON-NLS-1$
+
+ String s = "lastCheckpoint : int = " + String.valueOf(this.lastCheckPoint) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ s = s + "identifierStack : char["+(this.identifierPtr + 1)+"][] = {"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i <= this.identifierPtr; i++) {
s = s + "\"" + String.valueOf(this.identifierStack[i]) + "\","; //$NON-NLS-1$ //$NON-NLS-2$
}
s = s + "}\n"; //$NON-NLS-1$
- s = s + "identierLengthStack : int[] = {"; //$NON-NLS-1$
+ s = s + "identifierLengthStack : int["+(this.identifierLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i <= this.identifierLengthPtr; i++) {
s = s + this.identifierLengthStack[i] + ","; //$NON-NLS-1$
}
s = s + "}\n"; //$NON-NLS-1$
- s = s + "astLengthStack : int[] = {"; //$NON-NLS-1$
+ s = s + "astLengthStack : int["+(this.astLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i <= this.astLengthPtr; i++) {
s = s + this.astLengthStack[i] + ","; //$NON-NLS-1$
}
s = s + "}\n"; //$NON-NLS-1$
s = s + "astPtr : int = " + String.valueOf(this.astPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
- s = s + "intStack : int[] = {"; //$NON-NLS-1$
+ s = s + "intStack : int["+(this.intPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i <= this.intPtr; i++) {
s = s + this.intStack[i] + ","; //$NON-NLS-1$
}
s = s + "}\n"; //$NON-NLS-1$
- s = s + "expressionLengthStack : int[] = {"; //$NON-NLS-1$
+ s = s + "expressionLengthStack : int["+(this.expressionLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
for (int i = 0; i <= this.expressionLengthPtr; i++) {
s = s + this.expressionLengthStack[i] + ","; //$NON-NLS-1$
}
s = s + "}\n"; //$NON-NLS-1$
s = s + "expressionPtr : int = " + String.valueOf(this.expressionPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "genericsIdentifiersLengthStack : int["+(this.genericsIdentifiersLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.genericsIdentifiersLengthPtr; i++) {
+ s = s + this.genericsIdentifiersLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "genericsLengthStack : int["+(this.genericsLengthPtr + 1)+"] = {"; //$NON-NLS-1$ //$NON-NLS-2$
+ for (int i = 0; i <= this.genericsLengthPtr; i++) {
+ s = s + this.genericsLengthStack[i] + ","; //$NON-NLS-1$
+ }
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "genericsPtr : int = " + String.valueOf(this.genericsPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
s = s + "\n\n\n----------------Scanner--------------\n" + this.scanner.toString(); //$NON-NLS-1$
return s;
@@ -6234,11 +9347,11 @@ protected void updateSourceDeclarationParts(int variableDeclaratorsCounter) {
protected void updateSourcePosition(Expression exp) {
//update the source Position of the expression
- //intStack : int int
+ //this.intStack : int int
//-->
- //intStack :
+ //this.intStack :
exp.sourceEnd = this.intStack[this.intPtr--];
exp.sourceStart = this.intStack[this.intPtr--];
}
-}
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/src/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index bdb077b..6360b0f 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -12,25 +12,24 @@ package org.eclipse.jdt.internal.compiler.parser;
/*An interface that contains static declarations for some basic information
about the parser such as the number of rules in the grammar, the starting state, etc...*/
-
public interface ParserBasicInformation {
- public final static int
- ERROR_SYMBOL = 105,
- MAX_NAME_LENGTH = 36,
- NUM_STATES = 597,
- NT_OFFSET = 105,
- SCOPE_UBOUND = 63,
- SCOPE_SIZE = 64,
- LA_STATE_OFFSET = 5981,
- MAX_LA = 1,
- NUM_RULES = 433,
- NUM_TERMINALS = 105,
- NUM_NON_TERMINALS = 203,
- NUM_SYMBOLS = 308,
- START_STATE = 529,
- EOFT_SYMBOL = 54,
- EOLT_SYMBOL = 54,
- ACCEPT_ACTION = 5980,
- ERROR_ACTION = 5981;
-}
+ int ERROR_SYMBOL = 108,
+ MAX_NAME_LENGTH = 41,
+ NUM_STATES = 953,
+
+ NT_OFFSET = 108,
+ SCOPE_UBOUND = 132,
+ SCOPE_SIZE = 133,
+ LA_STATE_OFFSET = 12548,
+ MAX_LA = 1,
+ NUM_RULES = 691,
+ NUM_TERMINALS = 108,
+ NUM_NON_TERMINALS = 307,
+ NUM_SYMBOLS = 415,
+ START_STATE = 1129,
+ EOFT_SYMBOL = 67,
+ EOLT_SYMBOL = 67,
+ ACCEPT_ACTION = 12547,
+ ERROR_ACTION = 12548;
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
index 4133b61..a3849d4 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.compiler.parser;
/**
* Internal field structure for parsing recovery
*/
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Expression;
@@ -109,13 +110,22 @@ public String toString(int tab){
}
public FieldDeclaration updatedFieldDeclaration(){
- if (this.anonymousTypes != null && fieldDeclaration.initialization == null) {
- for (int i = 0; i < this.anonymousTypeCount; i++){
- if (anonymousTypes[i].preserveContent){
- fieldDeclaration.initialization = this.anonymousTypes[i].updatedTypeDeclaration().allocation;
+ if (this.anonymousTypes != null) {
+ if(fieldDeclaration.initialization == null) {
+ for (int i = 0; i < this.anonymousTypeCount; i++){
+ if (anonymousTypes[i].preserveContent){
+ fieldDeclaration.initialization = this.anonymousTypes[i].updatedTypeDeclaration().allocation;
+ }
+ }
+ if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
+ } else if(fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ // fieldDeclaration is an enum constant
+ for (int i = 0; i < this.anonymousTypeCount; i++){
+ if (anonymousTypes[i].preserveContent){
+ this.anonymousTypes[i].updatedTypeDeclaration();
+ }
}
}
- if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
}
return fieldDeclaration;
}
@@ -128,7 +138,14 @@ public FieldDeclaration updatedFieldDeclaration(){
public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
if (bracketBalance > 0){ // was an array initializer
bracketBalance--;
- if (bracketBalance == 0) alreadyCompletedFieldInitialization = true;
+ if (bracketBalance == 0) {
+ if(fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+ updateSourceEndIfNecessary(braceEnd - 1);
+ return parent;
+ } else {
+ alreadyCompletedFieldInitialization = true;
+ }
+ }
return this;
} else if (bracketBalance == 0) {
alreadyCompletedFieldInitialization = true;
@@ -150,6 +167,11 @@ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
bracketBalance++;
return null; // no update is necessary (array initializer)
}
+ if (fieldDeclaration.declarationSourceEnd == 0
+ && fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT){
+ bracketBalance++;
+ return null; // no update is necessary (enum constant)
+ }
// might be an array initializer
this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);
return this.parent.updateOnOpeningBrace(braceStart, braceEnd);
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
index 66d1aae..ed9d6c3 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
@@ -156,7 +156,7 @@ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceV
}
RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
localTypes[localTypeCount++] = element;
-
+
/* consider that if the opening brace was not found, it is there */
if (!foundOpeningBrace){
foundOpeningBrace = true;
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
index b76bf04..64e38f5 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
@@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
@@ -212,7 +213,7 @@ public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceV
}
return methodBody.add(typeDeclaration, bracketBalanceValue, true);
}
- if (typeDeclaration.isInterface()) {
+ if (typeDeclaration.kind() == IGenericType.INTERFACE_DECL) {
this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
if (this.parent == null) {
return this; // ignore
@@ -391,7 +392,7 @@ public void updateFromParserState(){
}
}
if(canConsume) {
- parser.consumeMethodHeaderParameters();
+ parser.consumeMethodHeaderRightParen();
/* fix-up positions, given they were updated against rParenPos, which did not get set */
if (parser.currentElement == this){ // parameter addition might have added an awaiting (no return type) method - see 1FVXQZ4 */
methodDeclaration.sourceEnd = methodDeclaration.arguments[methodDeclaration.arguments.length-1].sourceEnd;
@@ -404,6 +405,16 @@ public void updateFromParserState(){
}
}
}
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+ if(this.methodDeclaration.isAnnotationMethod()) {
+ this.updateSourceEndIfNecessary(braceStart, braceEnd);
+ if(!this.foundOpeningBrace && this.parent != null) {
+ return this.parent.updateOnClosingBrace(braceStart, braceEnd);
+ }
+ return this;
+ }
+ return super.updateOnClosingBrace(braceStart, braceEnd);
+}
/*
* An opening brace got consumed, might be the expected opening one of the current element,
* in which case the bodyStart is updated.
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
index 9ac355e..c93242e 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
@@ -12,12 +12,15 @@ package org.eclipse.jdt.internal.compiler.parser;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
/**
@@ -37,10 +40,13 @@ public class RecoveredType extends RecoveredStatement implements TerminalTokens,
public boolean preserveContent = false; // only used for anonymous types
public int bodyEnd;
+ public boolean insideEnumConstantPart = false;
+
public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){
super(typeDeclaration, parent, bracketBalance);
this.typeDeclaration = typeDeclaration;
this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
+ this.insideEnumConstantPart = typeDeclaration.kind() == IGenericType.ENUM_DECL;
if(this.foundOpeningBrace) {
this.bracketBalance++;
}
@@ -69,6 +75,8 @@ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bra
}
RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
methods[methodCount++] = element;
+
+ this.insideEnumConstantPart = false;
/* consider that if the opening brace was not found, it is there */
if (!foundOpeningBrace){
@@ -107,9 +115,19 @@ public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanc
fieldCount);
}
}
- RecoveredField element = fieldDeclaration.isField()
- ? new RecoveredField(fieldDeclaration, this, bracketBalanceValue)
- : new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
+ RecoveredField element;
+ switch (fieldDeclaration.getKind()) {
+ case AbstractVariableDeclaration.FIELD:
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ element = new RecoveredField(fieldDeclaration, this, bracketBalanceValue);
+ break;
+ case AbstractVariableDeclaration.INITIALIZER:
+ element = new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
+ break;
+ default:
+ // never happens, as field is always identified
+ return this;
+ }
fields[fieldCount++] = element;
/* consider that if the opening brace was not found, it is there */
@@ -130,6 +148,8 @@ public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBa
return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
}
+ this.insideEnumConstantPart = false;
+
if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
if (this.methodCount > 0) {
// add it to the last method body
@@ -179,7 +199,11 @@ public int bodyEnd(){
public boolean bodyStartsAtHeaderEnd(){
if (typeDeclaration.superInterfaces == null){
if (typeDeclaration.superclass == null){
- return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
+ if(typeDeclaration.typeParameters == null) {
+ return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
+ } else {
+ return typeDeclaration.bodyStart == typeDeclaration.typeParameters[typeDeclaration.typeParameters.length-1].sourceEnd+1;
+ }
} else {
return typeDeclaration.bodyStart == typeDeclaration.superclass.sourceEnd+1;
}
@@ -306,12 +330,14 @@ public TypeDeclaration updatedTypeDeclaration(){
/* update methods */
int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
boolean hasConstructor = false, hasRecoveredConstructor = false;
+ boolean hasAbstractMethods = false;
int defaultConstructorIndex = -1;
if (methodCount > 0){
AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[existingCount + methodCount];
for (int i = 0; i < existingCount; i++){
AbstractMethodDeclaration m = typeDeclaration.methods[i];
if (m.isDefaultConstructor()) defaultConstructorIndex = i;
+ if (m.isAbstract()) hasAbstractMethods = true;
methodDeclarations[i] = m;
}
// may need to update the declarationSourceEnd of the last method
@@ -323,9 +349,11 @@ public TypeDeclaration updatedTypeDeclaration(){
for (int i = 0; i < methodCount; i++){
AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration();
if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
+ if (updatedMethod.isAbstract()) hasAbstractMethods = true;
methodDeclarations[existingCount + i] = updatedMethod;
}
typeDeclaration.methods = methodDeclarations;
+ if (hasAbstractMethods) typeDeclaration.bits |= ASTNode.HasAbstractMethods;
hasConstructor = typeDeclaration.checkConstructors(this.parser());
} else {
for (int i = 0; i < existingCount; i++){
@@ -360,7 +388,7 @@ public TypeDeclaration updatedTypeDeclaration(){
}
typeDeclaration.methods = methodDeclarations;
} else {
- if (!hasConstructor && !typeDeclaration.isInterface()) {// if was already reduced, then constructor
+ if (!hasConstructor && typeDeclaration.kind() != IGenericType.INTERFACE_DECL && typeDeclaration.kind() != IGenericType.ANNOTATION_TYPE_DECL) {// if was already reduced, then constructor
boolean insideFieldInitializer = false;
RecoveredElement parentElement = this.parent;
while (parentElement != null){
@@ -370,7 +398,7 @@ public TypeDeclaration updatedTypeDeclaration(){
}
parentElement = parentElement.parent;
}
- typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
+ typeDeclaration.createDefaultConstructor(!parser().diet || insideFieldInitializer, true);
}
}
if (parent instanceof RecoveredType){
@@ -409,6 +437,30 @@ public void updateFromParserState(){
// will reset typeListLength to zero
// thus this check will only be performed on first errorCheck after class X implements Y,Z,
}
+ } else if (parser.listTypeParameterLength > 0) {
+ int length = parser.listTypeParameterLength;
+ int genericsPtr = parser.genericsPtr;
+ boolean canConsume = genericsPtr + 1 >= length && parser.astPtr > -1;
+ if(canConsume) {
+ if (!(parser.astStack[parser.astPtr] instanceof TypeDeclaration)) {
+ canConsume = false;
+ }
+ while(genericsPtr + 1 > length && !(parser.genericsStack[genericsPtr] instanceof TypeParameter)) {
+ genericsPtr--;
+ }
+ for (int i = 0; i < length; i++) {
+ if(!(parser.genericsStack[genericsPtr - i] instanceof TypeParameter)) {
+ canConsume = false;
+ }
+ }
+ }
+ if(canConsume) {
+ TypeDeclaration typeDecl = (TypeDeclaration)parser.astStack[parser.astPtr];
+ System.arraycopy(parser.genericsStack, genericsPtr - length + 1, typeDecl.typeParameters = new TypeParameter[length], 0, length);
+ typeDecl.bodyStart = typeDecl.typeParameters[length-1].declarationSourceEnd + 1;
+ parser.listTypeParameterLength = 0;
+ parser.lastCheckPoint = typeDecl.bodyStart;
+ }
}
}
}
@@ -440,6 +492,9 @@ public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
case -1 :
case TokenNameextends :
case TokenNameimplements :
+ case TokenNameGREATER :
+ case TokenNameRIGHT_SHIFT :
+ case TokenNameUNSIGNED_RIGHT_SHIFT :
if (parser.recoveredStaticInitializerStart == 0) break;
default:
this.foundOpeningBrace = true;
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
index 61b1f53..73a9e49 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
@@ -15,9 +15,11 @@ package org.eclipse.jdt.internal.compiler.parser;
*/
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
public class RecoveredUnit extends RecoveredElement {
@@ -40,9 +42,21 @@ public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bra
/* attach it to last type - if any */
if (this.typeCount > 0){
RecoveredType type = this.types[this.typeCount -1];
+ int start = type.bodyEnd;
+ int end = type.typeDeclaration.bodyEnd;
type.bodyEnd = 0; // reset position
type.typeDeclaration.declarationSourceEnd = 0; // reset position
type.typeDeclaration.bodyEnd = 0;
+
+ if(start > 0 && start < end) {
+ Initializer initializer = new Initializer(new Block(0), 0);
+ initializer.bodyStart = end;
+ initializer.bodyEnd = end;
+ initializer.declarationSourceStart = end;
+ initializer.declarationSourceEnd = end;
+ type.add(initializer, bracketBalanceValue);
+ }
+
return type.add(methodDeclaration, bracketBalanceValue);
}
return this; // ignore
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/src/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 70e8242..6ec4cf4 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -14,6 +14,7 @@ import java.util.Iterator;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -34,13 +35,15 @@ public class Scanner implements TerminalTokens {
- sourceStart gives the position into the stream
- currentPosition-1 gives the sourceEnd position into the stream
*/
-
+ protected long sourceLevel;
// 1.4 feature
- private boolean assertMode = false;
public boolean useAssertAsAnIndentifier = false;
//flag indicating if processed source contains occurrences of keyword assert
public boolean containsAssertKeyword = false;
+ // 1.5 feature
+ public boolean useEnumAsAnIndentifier = false;
+
public boolean recordLineSeparator = false;
public char currentCharacter;
public int startPosition;
@@ -101,6 +104,7 @@ public class Scanner implements TerminalTokens {
public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
+ public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$
//----------------optimized identifier managment------------------
static final char[] charArray_a = new char[] {'a'},
@@ -137,7 +141,7 @@ public class Scanner implements TerminalTokens {
public /*static*/ final char[][][][] charArray_length =
new char[OptimizedLength][TableSize][InternalTableSize][];
// support for detecting non-externalized string literals
- NLSLine currentLine= null;
+ public NLSLine currentLine= null;
public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
public static final String TAG_POSTFIX= "$"; //$NON-NLS-1$
@@ -146,6 +150,9 @@ public class Scanner implements TerminalTokens {
public boolean checkNonExternalizedStringLiterals = false;
public boolean wasNonExternalizedStringLiteral = false;
+ // generic support
+ public boolean returnOnlyGreater = false;
+
/*static*/ {
for (int i = 0; i < 6; i++) {
for (int j = 0; j < TableSize; j++) {
@@ -183,7 +190,7 @@ public Scanner(
this.tokenizeComments = tokenizeComments;
this.tokenizeWhiteSpace = tokenizeWhiteSpace;
this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
- this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
+ this.sourceLevel = sourceLevel;
this.taskTags = taskTags;
this.taskPriorities = taskPriorities;
this.isTaskCaseSensitive = isTaskCaseSensitive;
@@ -196,7 +203,7 @@ public final boolean atEnd() {
return this.source.length == this.currentPosition;
}
-private void checkNonExternalizedString() {
+protected void checkNonExternalizedString() {
if (this.currentLine == null)
return;
parseTags(this.currentLine);
@@ -925,6 +932,13 @@ public int getNextToken() throws InvalidInputException {
// ---------Identify the next token-------------
switch (this.currentCharacter) {
+ case '@' :
+/* if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+ return TokenNameAT;
+ } else {
+ return TokenNameERROR;
+ }*/
+ return TokenNameAT;
case '(' :
return TokenNameLPAREN;
case ')' :
@@ -942,9 +956,37 @@ public int getNextToken() throws InvalidInputException {
case ',' :
return TokenNameCOMMA;
case '.' :
- if (getNextCharAsDigit())
+ if (getNextCharAsDigit()) {
return scanNumber(true);
- return TokenNameDOT;
+ }
+/* if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+ int temp = this.currentPosition;
+ if (getNextChar('.')) {
+ if (getNextChar('.')) {
+ return TokenNameELLIPSIS;
+ } else {
+ this.currentPosition = temp;
+ return TokenNameDOT;
+ }
+ } else {
+ this.currentPosition = temp;
+ return TokenNameDOT;
+ }
+ } else {
+ return TokenNameDOT;
+ }*/
+ int temp = this.currentPosition;
+ if (getNextChar('.')) {
+ if (getNextChar('.')) {
+ return TokenNameELLIPSIS;
+ } else {
+ this.currentPosition = temp;
+ return TokenNameDOT;
+ }
+ } else {
+ this.currentPosition = temp;
+ return TokenNameDOT;
+ }
case '+' :
{
int test;
@@ -992,6 +1034,9 @@ public int getNextToken() throws InvalidInputException {
case '>' :
{
int test;
+ if (this.returnOnlyGreater) {
+ return TokenNameGREATER;
+ }
if ((test = getNextChar('=', '>')) == 0)
return TokenNameGREATER_EQUAL;
if (test > 0) {
@@ -1367,7 +1412,9 @@ public int getNextToken() throws InvalidInputException {
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
checkNonExternalizedString();
if (this.recordLineSeparator) {
- if (!isUnicode) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
pushLineSeparator();
}
} else {
@@ -1397,7 +1444,9 @@ public int getNextToken() throws InvalidInputException {
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
checkNonExternalizedString();
if (this.recordLineSeparator) {
- if (!isUnicode) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
pushLineSeparator();
}
} else {
@@ -1450,8 +1499,9 @@ public int getNextToken() throws InvalidInputException {
default :
if (Character.isJavaIdentifierStart(this.currentCharacter))
return scanIdentifierOrKeyword();
- if (isDigit(this.currentCharacter))
+ if (isDigit(this.currentCharacter)) {
return scanNumber(false);
+ }
return TokenNameERROR;
}
}
@@ -1513,7 +1563,7 @@ public final void getNextUnicodeChar()
public char[] getSource(){
return this.source;
}
-private boolean isDigit(char c) throws InvalidInputException {
+protected boolean isDigit(char c) throws InvalidInputException {
if (Character.isDigit(c)) {
switch(c) {
case '0' :
@@ -1528,7 +1578,7 @@ private boolean isDigit(char c) throws InvalidInputException {
case '9' :
return true;
}
- throw new InvalidInputException(Scanner.INVALID_INPUT);
+ throw new InvalidInputException(Scanner.INVALID_DIGIT);
} else {
return false;
}
@@ -2164,7 +2214,7 @@ final char[] optimizedCurrentTokenSource6() {
newEntry6 = max;
return r;
}
-private void parseTags(NLSLine line) {
+protected void parseTags(NLSLine line) {
String s = new String(getCurrentTokenSource());
int pos = s.indexOf(TAG_PREFIX);
int lineLength = line.size();
@@ -2413,6 +2463,7 @@ public int scanIdentifierOrKeyword() {
//keywors with the same length AND the same first char, then do another
//dispatch on the second char
this.useAssertAsAnIndentifier = false;
+ this.useEnumAsAnIndentifier = false;
while (getNextCharAsJavaIdentifierPart()){/*empty*/}
int index, length;
@@ -2459,7 +2510,7 @@ public int scanIdentifierOrKeyword() {
&& (data[++index] == 'e')
&& (data[++index] == 'r')
&& (data[++index] == 't')) {
- if (this.assertMode) {
+ if (this.sourceLevel >= ClassFileConstants.JDK1_4) {
this.containsAssertKeyword = true;
return TokenNameassert;
} else {
@@ -2584,8 +2635,18 @@ public int scanIdentifierOrKeyword() {
case 4 :
if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
return TokenNameelse;
- else
- return TokenNameIdentifier;
+ else if ((data[index] == 'n')
+ && (data[++index] == 'u')
+ && (data[++index] == 'm')) {
+ if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
+ return TokenNameenum;
+ } else {
+ this.useEnumAsAnIndentifier = true;
+ return TokenNameIdentifier;
+ }
+ } else {
+ return TokenNameIdentifier;
+ }
case 7 :
if ((data[++index] == 'x')
&& (data[++index] == 't')
@@ -2985,25 +3046,114 @@ public int scanNumber(boolean dotPrefix) throws InvalidInputException {
boolean floating = dotPrefix;
if ((!dotPrefix) && (this.currentCharacter == '0')) {
if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
- //force the first char of the hexa number do exist...
- // consume next character
- this.unicodeAsBackSlash = false;
- if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
- && (this.source[this.currentPosition] == 'u')) {
- getNextUnicodeChar();
- } else {
- if (this.withoutUnicodePtr != 0) {
- unicodeStoreAt(++this.withoutUnicodePtr);
- }
- }
- if (Character.digit(this.currentCharacter, 16) == -1)
- throw new InvalidInputException(INVALID_HEXA);
- //---end forcing--
+ int start = this.currentPosition;
while (getNextCharAsDigit(16)){/*empty*/}
- if (getNextChar('l', 'L') >= 0)
+ int end = this.currentPosition;
+ if (getNextChar('l', 'L') >= 0) {
+ if (end == start) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
return TokenNameLongLiteral;
- else
+ } else if (getNextChar('.')) {
+ if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+ // if we are in source level < 1.5, we report an integer literal
+ this.currentPosition = end;
+ return TokenNameIntegerLiteral;
+ }
+ // hexadeciman floating point literal
+ // read decimal part
+ boolean hasNoDigitsBeforeDot = end == start;
+ start = this.currentPosition;
+ while (getNextCharAsDigit(16)){/*empty*/}
+ end = this.currentPosition;
+ if (hasNoDigitsBeforeDot && end == start) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
+
+ if (getNextChar('p', 'P') >= 0) { // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+
+ if ((this.currentCharacter == '-')
+ || (this.currentCharacter == '+')) { // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+ }
+ if (!isDigit(this.currentCharacter)) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
+ while (getNextCharAsDigit()){/*empty*/}
+ if (getNextChar('f', 'F') >= 0) {
+ return TokenNameFloatingPointLiteral;
+ }
+ if (getNextChar('d', 'D') >= 0) {
+ return TokenNameDoubleLiteral;
+ }
+ if (getNextChar('l', 'L') >= 0) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
+ return TokenNameDoubleLiteral;
+ } else {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
+ } else if (getNextChar('p', 'P') >= 0) { // consume next character
+ if (this.sourceLevel < ClassFileConstants.JDK1_5) {
+ // if we are in source level < 1.5 we report an integer literal
+ this.currentPosition = end;
+ return TokenNameIntegerLiteral;
+ }
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+
+ if ((this.currentCharacter == '-')
+ || (this.currentCharacter == '+')) { // consume next character
+ this.unicodeAsBackSlash = false;
+ if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+ && (this.source[this.currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStoreAt(++this.withoutUnicodePtr);
+ }
+ }
+ }
+ if (!isDigit(this.currentCharacter))
+ throw new InvalidInputException(INVALID_FLOAT);
+ while (getNextCharAsDigit()){/*empty*/}
+ if (getNextChar('f', 'F') >= 0)
+ return TokenNameFloatingPointLiteral;
+ if (getNextChar('d', 'D') >= 0)
+ return TokenNameDoubleLiteral;
+ if (getNextChar('l', 'L') >= 0) {
+ throw new InvalidInputException(INVALID_HEXA);
+ }
+ return TokenNameDoubleLiteral;
+ } else {
+ if (end == start)
+ throw new InvalidInputException(INVALID_HEXA);
return TokenNameIntegerLiteral;
+ }
}
//there is x or X in the number
@@ -3161,6 +3311,21 @@ public final void setSource(char[] sourceString){
this.eofPosition = sourceLength;
this.initialPosition = this.currentPosition = 0;
this.containsAssertKeyword = false;
+ this.linePtr = -1;
+}
+
+/*
+ * Should be used if a parse (usually a diet parse) has already been performed on the unit,
+ * so as to get the already computed line end positions.
+ */
+public final void setSource(CompilationResult compilationResult) {
+ char[] contents = compilationResult.compilationUnit.getContents();
+ setSource(contents);
+ int[] lineSeparatorPositions = compilationResult.lineSeparatorPositions;
+ if (lineSeparatorPositions != null) {
+ this.lineEnds = lineSeparatorPositions;
+ this.linePtr = lineSeparatorPositions.length - 1;
+ }
}
public String toString() {
@@ -3200,7 +3365,7 @@ public String toString() {
+ "<-- Ends here\n===============================\n" //$NON-NLS-1$
+ new String(end);
}
-public final String toStringAction(int act) {
+public String toStringAction(int act) {
switch (act) {
case TokenNameIdentifier :
return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/src/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
index c05ff33..45ea344 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
@@ -8,9 +8,8 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-
package org.eclipse.jdt.internal.compiler.parser;
-
+
/**
* IMPORTANT NOTE: These constants are dedicated to the internal Scanner implementation.
* It is mirrored in org.eclipse.jdt.core.compiler public package where it is API.
@@ -18,7 +17,6 @@ package org.eclipse.jdt.internal.compiler.parser;
* definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens
* which constant values reflect the latest parser generation state.
*/
-
/**
* Maps each terminal symbol in the java-grammar into a unique integer.
* This integer is used to represent the terminal when computing a parsing action.
@@ -30,116 +28,117 @@ package org.eclipse.jdt.internal.compiler.parser;
public interface TerminalTokens {
// special tokens not part of grammar - not autogenerated
- int
- TokenNameWHITESPACE = 1000,
+ int TokenNameWHITESPACE = 1000,
TokenNameCOMMENT_LINE = 1001,
TokenNameCOMMENT_BLOCK = 1002,
TokenNameCOMMENT_JAVADOC = 1003;
-
- int
- TokenNameIdentifier = 28,
- TokenNameabstract = 60,
- TokenNameassert = 71,
- TokenNameboolean = 31,
- TokenNamebreak = 72,
- TokenNamebyte = 32,
- TokenNamecase = 83,
- TokenNamecatch = 86,
- TokenNamechar = 33,
- TokenNameclass = 81,
- TokenNamecontinue = 73,
- TokenNamedefault = 84,
- TokenNamedo = 74,
- TokenNamedouble = 34,
- TokenNameelse = 87,
- TokenNameextends = 91,
- TokenNamefalse = 44,
- TokenNamefinal = 61,
- TokenNamefinally = 88,
- TokenNamefloat = 35,
- TokenNamefor = 75,
- TokenNameif = 76,
- TokenNameimplements = 103,
- TokenNameimport = 82,
- TokenNameinstanceof = 13,
- TokenNameint = 36,
- TokenNameinterface = 89,
- TokenNamelong = 37,
- TokenNamenative = 62,
- TokenNamenew = 41,
- TokenNamenull = 45,
- TokenNamepackage = 85,
- TokenNameprivate = 63,
- TokenNameprotected = 64,
- TokenNamepublic = 65,
- TokenNamereturn = 77,
- TokenNameshort = 38,
- TokenNamestatic = 57,
- TokenNamestrictfp = 66,
- TokenNamesuper = 42,
- TokenNameswitch = 78,
- TokenNamesynchronized = 55,
- TokenNamethis = 43,
- TokenNamethrow = 79,
- TokenNamethrows = 104,
- TokenNametransient = 67,
- TokenNametrue = 46,
- TokenNametry = 80,
- TokenNamevoid = 39,
- TokenNamevolatile = 68,
- TokenNamewhile = 70,
- TokenNameIntegerLiteral = 47,
- TokenNameLongLiteral = 48,
- TokenNameFloatingPointLiteral = 49,
- TokenNameDoubleLiteral = 50,
- TokenNameCharacterLiteral = 51,
- TokenNameStringLiteral = 52,
- TokenNamePLUS_PLUS = 7,
- TokenNameMINUS_MINUS = 8,
- TokenNameEQUAL_EQUAL = 18,
- TokenNameLESS_EQUAL = 14,
- TokenNameGREATER_EQUAL = 15,
- TokenNameNOT_EQUAL = 19,
- TokenNameLEFT_SHIFT = 11,
- TokenNameRIGHT_SHIFT = 9,
- TokenNameUNSIGNED_RIGHT_SHIFT = 10,
- TokenNamePLUS_EQUAL = 92,
- TokenNameMINUS_EQUAL = 93,
- TokenNameMULTIPLY_EQUAL = 94,
- TokenNameDIVIDE_EQUAL = 95,
- TokenNameAND_EQUAL = 96,
- TokenNameOR_EQUAL = 97,
- TokenNameXOR_EQUAL = 98,
- TokenNameREMAINDER_EQUAL = 99,
- TokenNameLEFT_SHIFT_EQUAL = 100,
- TokenNameRIGHT_SHIFT_EQUAL = 101,
- TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 102,
- TokenNameOR_OR = 24,
- TokenNameAND_AND = 25,
- TokenNamePLUS = 1,
- TokenNameMINUS = 2,
- TokenNameNOT = 58,
- TokenNameREMAINDER = 5,
- TokenNameXOR = 21,
- TokenNameAND = 20,
- TokenNameMULTIPLY = 4,
- TokenNameOR = 22,
- TokenNameTWIDDLE = 56,
- TokenNameDIVIDE = 6,
- TokenNameGREATER = 16,
- TokenNameLESS = 17,
- TokenNameLPAREN = 27,
- TokenNameRPAREN = 29,
- TokenNameLBRACE = 59,
- TokenNameRBRACE = 40,
- TokenNameLBRACKET = 12,
- TokenNameRBRACKET = 69,
- TokenNameSEMICOLON = 23,
- TokenNameQUESTION = 26,
- TokenNameCOLON = 53,
- TokenNameCOMMA = 30,
- TokenNameDOT = 3,
- TokenNameEQUAL = 90,
- TokenNameEOF = 54,
- TokenNameERROR = 105;
-}
+
+ int TokenNameIdentifier = 26,
+ TokenNameabstract = 56,
+ TokenNameassert = 74,
+ TokenNameboolean = 32,
+ TokenNamebreak = 75,
+ TokenNamebyte = 33,
+ TokenNamecase = 100,
+ TokenNamecatch = 101,
+ TokenNamechar = 34,
+ TokenNameclass = 72,
+ TokenNamecontinue = 76,
+ TokenNamedefault = 96,
+ TokenNamedo = 77,
+ TokenNamedouble = 35,
+ TokenNameelse = 102,
+ TokenNameenum = 103,
+ TokenNameextends = 97,
+ TokenNamefalse = 45,
+ TokenNamefinal = 57,
+ TokenNamefinally = 104,
+ TokenNamefloat = 36,
+ TokenNamefor = 78,
+ TokenNameif = 79,
+ TokenNameimplements = 106,
+ TokenNameimport = 99,
+ TokenNameinstanceof = 15,
+ TokenNameint = 37,
+ TokenNameinterface = 80,
+ TokenNamelong = 38,
+ TokenNamenative = 58,
+ TokenNamenew = 43,
+ TokenNamenull = 46,
+ TokenNamepackage = 98,
+ TokenNameprivate = 59,
+ TokenNameprotected = 60,
+ TokenNamepublic = 61,
+ TokenNamereturn = 81,
+ TokenNameshort = 39,
+ TokenNamestatic = 54,
+ TokenNamestrictfp = 62,
+ TokenNamesuper = 41,
+ TokenNameswitch = 82,
+ TokenNamesynchronized = 55,
+ TokenNamethis = 42,
+ TokenNamethrow = 83,
+ TokenNamethrows = 105,
+ TokenNametransient = 63,
+ TokenNametrue = 47,
+ TokenNametry = 84,
+ TokenNamevoid = 40,
+ TokenNamevolatile = 64,
+ TokenNamewhile = 73,
+ TokenNameIntegerLiteral = 48,
+ TokenNameLongLiteral = 49,
+ TokenNameFloatingPointLiteral = 50,
+ TokenNameDoubleLiteral = 51,
+ TokenNameCharacterLiteral = 52,
+ TokenNameStringLiteral = 53,
+ TokenNamePLUS_PLUS = 10,
+ TokenNameMINUS_MINUS = 11,
+ TokenNameEQUAL_EQUAL = 18,
+ TokenNameLESS_EQUAL = 16,
+ TokenNameGREATER_EQUAL = 17,
+ TokenNameNOT_EQUAL = 19,
+ TokenNameLEFT_SHIFT = 13,
+ TokenNameRIGHT_SHIFT = 8,
+ TokenNameUNSIGNED_RIGHT_SHIFT = 9,
+ TokenNamePLUS_EQUAL = 85,
+ TokenNameMINUS_EQUAL = 86,
+ TokenNameMULTIPLY_EQUAL = 87,
+ TokenNameDIVIDE_EQUAL = 88,
+ TokenNameAND_EQUAL = 89,
+ TokenNameOR_EQUAL = 90,
+ TokenNameXOR_EQUAL = 91,
+ TokenNameREMAINDER_EQUAL = 92,
+ TokenNameLEFT_SHIFT_EQUAL = 93,
+ TokenNameRIGHT_SHIFT_EQUAL = 94,
+ TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 95,
+ TokenNameOR_OR = 25,
+ TokenNameAND_AND = 24,
+ TokenNamePLUS = 1,
+ TokenNameMINUS = 2,
+ TokenNameNOT = 68,
+ TokenNameREMAINDER = 5,
+ TokenNameXOR = 21,
+ TokenNameAND = 20,
+ TokenNameMULTIPLY = 4,
+ TokenNameOR = 22,
+ TokenNameTWIDDLE = 69,
+ TokenNameDIVIDE = 6,
+ TokenNameGREATER = 12,
+ TokenNameLESS = 7,
+ TokenNameLPAREN = 28,
+ TokenNameRPAREN = 29,
+ TokenNameLBRACE = 66,
+ TokenNameRBRACE = 31,
+ TokenNameLBRACKET = 14,
+ TokenNameRBRACKET = 70,
+ TokenNameSEMICOLON = 27,
+ TokenNameQUESTION = 23,
+ TokenNameCOLON = 65,
+ TokenNameCOMMA = 30,
+ TokenNameDOT = 3,
+ TokenNameEQUAL = 71,
+ TokenNameAT = 44,
+ TokenNameELLIPSIS = 107,
+ TokenNameEOF = 67,
+ TokenNameERROR = 108;
+}
\ No newline at end of file
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
index 58e0506..6c53f6a 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.compiler.parser.diagnose;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
@@ -18,6 +19,7 @@ import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
private static final boolean DEBUG = false;
+ private boolean DEBUG_PARSECHECK = false;
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static final int STACK_INCREMENT = 256;
@@ -39,6 +41,8 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
private static final int MAX_DISTANCE = 30;
private static final int MIN_DISTANCE = 3;
+ private CompilerOptions options;
+
private LexStream lexStream;
private int errorToken;
private int errorTokenStart;
@@ -133,12 +137,13 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
}
}
- public DiagnoseParser(Parser parser, int firstToken, int start, int end) {
- this(parser, firstToken, start, end, new int[0], new int[0], new int[0]);
+ public DiagnoseParser(Parser parser, int firstToken, int start, int end, CompilerOptions options) {
+ this(parser, firstToken, start, end, new int[0], new int[0], new int[0], options);
}
- public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip) {
+ public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, CompilerOptions options) {
this.parser = parser;
+ this.options = options;
this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end);
}
@@ -1912,6 +1917,9 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
act = stck[stack_top];
if (first_token > NT_OFFSET) {
tempStackTop = stack_top;
+ if(DEBUG_PARSECHECK) {
+ System.out.println(tempStackTop);
+ }
max_pos = stack_top;
indx = buffer_position;
ct = lexStream.kind(buffer[indx]);
@@ -1919,8 +1927,26 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
int lhs_symbol = first_token - NT_OFFSET;
act = Parser.ntAction(act, lhs_symbol);
if (act <= NUM_RULES) {
+ // same loop as 'process_non_terminal'
do {
tempStackTop -= (Parser.rhs[act]-1);
+
+ if(DEBUG_PARSECHECK) {
+ System.out.print(tempStackTop);
+ System.out.print(" ("); //$NON-NLS-1$
+ System.out.print(-(Parser.rhs[act]-1));
+ System.out.print(") [max:"); //$NON-NLS-1$
+ System.out.print(max_pos);
+ System.out.print("]\tprocess_non_terminal\t"); //$NON-NLS-1$
+ System.out.print(act);
+ System.out.print("\t"); //$NON-NLS-1$
+ System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]);
+ System.out.println();
+ }
+
+ if(Parser.rules_compliance[act] > this.options.sourceLevel) {
+ return 0;
+ }
lhs_symbol = Parser.lhs[act];
act = (tempStackTop > max_pos
? tempStack[tempStackTop]
@@ -1932,6 +1958,11 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
}
} else {
tempStackTop = stack_top - 1;
+
+ if(DEBUG_PARSECHECK) {
+ System.out.println(tempStackTop);
+ }
+
max_pos = tempStackTop;
indx = buffer_position - 1;
ct = first_token;
@@ -1939,6 +1970,17 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
}
process_terminal: for (;;) {
+ if(DEBUG_PARSECHECK) {
+ System.out.print(tempStackTop + 1);
+ System.out.print(" (+1) [max:"); //$NON-NLS-1$
+ System.out.print(max_pos);
+ System.out.print("]\tprocess_terminal \t"); //$NON-NLS-1$
+ System.out.print(ct);
+ System.out.print("\t"); //$NON-NLS-1$
+ System.out.print(Parser.name[Parser.terminal_index[ct]]);
+ System.out.println();
+ }
+
if (++tempStackTop >= stackLength) // Stack overflow!!!
return indx;
tempStack[tempStackTop] = act;
@@ -1947,6 +1989,14 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
if (act <= NUM_RULES) { // reduce action
tempStackTop--;
+
+ if(DEBUG_PARSECHECK) {
+ System.out.print(tempStackTop);
+ System.out.print(" (-1) [max:"); //$NON-NLS-1$
+ System.out.print(max_pos);
+ System.out.print("]\treduce"); //$NON-NLS-1$
+ System.out.println();
+ }
} else if (act < ACCEPT_ACTION || // shift action
act > ERROR_ACTION) { // shift-reduce action
if (indx == MAX_DISTANCE)
@@ -1955,8 +2005,17 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
ct = lexStream.kind(buffer[indx]);
lexStream.reset(lexStream.next(buffer[indx]));
if (act > ERROR_ACTION) {
- act -= ERROR_ACTION;
+ act -= ERROR_ACTION;
+
+ if(DEBUG_PARSECHECK) {
+ System.out.print(tempStackTop);
+ System.out.print("\tshift reduce"); //$NON-NLS-1$
+ System.out.println();
+ }
} else {
+ if(DEBUG_PARSECHECK) {
+ System.out.println("\tshift"); //$NON-NLS-1$
+ }
continue process_terminal;
}
} else if (act == ACCEPT_ACTION) { // accept action
@@ -1965,9 +2024,29 @@ public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
return indx; // error action
}
+ // same loop as first token initialization
process_non_terminal:
do {
tempStackTop -= (Parser.rhs[act]-1);
+
+ if(DEBUG_PARSECHECK) {
+ System.out.print(tempStackTop);
+ System.out.print(" ("); //$NON-NLS-1$
+ System.out.print(-(Parser.rhs[act]-1));
+ System.out.print(") [max:"); //$NON-NLS-1$
+ System.out.print(max_pos);
+ System.out.print("]\tprocess_non_terminal\t"); //$NON-NLS-1$
+ System.out.print(act);
+ System.out.print("\t"); //$NON-NLS-1$
+ System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]);
+ System.out.println();
+ }
+
+ if(act <= NUM_RULES) {
+ if(Parser.rules_compliance[act] > this.options.sourceLevel) {
+ return 0;
+ }
+ }
int lhs_symbol = Parser.lhs[act];
act = (tempStackTop > max_pos
? tempStack[tempStackTop]
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java b/src/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
index 4c53fa2..00b8d97 100644
--- a/src/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
+++ b/src/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
@@ -158,7 +158,7 @@ public class RangeUtil {
for (int i = 0; i < length; i++) {
if (fields[i] instanceof Initializer) {
Initializer initializer = (Initializer)fields[i];
- if(initializer.declarationSourceEnd == initializer.bodyEnd){
+ if(initializer.declarationSourceEnd == initializer.bodyEnd && initializer.declarationSourceStart != initializer.declarationSourceEnd){
initializer.errorInSignature = true;
result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
} else {
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index a35d6d8dafb03c45c156feda0c7d48c3e3f22f9f..8d6c3d9d4bf824b4e1ed4e9f3287bc487df46d0b 100644
GIT binary patch
literal 25302
zcmd5_2bdH^7Jk(^huIuKz!g~1BB&?o0g6kI6%bs4Vt`YWz4Oo$0pqD4s3!<3x^f;W
zryd}|!%Q&3f&@Vn6JlIE(NoWWWbRdW*W_6kM!#?Qzn!k`u6pnNRj*!!?im1xaAbfI
z2NhK4ix5CW2nZ<*8DuyK(H2pTXa}dj$pQWh9D)E(L}J7O-X%J`mkdNkCDJ;0uyXvY`QX;$H)NiJ(V@C*eQv1O>?@xzHWD!DEQO1h^KiLVQK?
z;NNgg4E_!g^oQga0#)!3oR2s=2Is;6_y<&z`~U@{0KSG@h!+q8VJ-}XLGUnqi}(&+
zL<~j@LkvfZfD7RQxClnVNK!yXCK8Ozy
zA#lCFm9P>fAkKnH#F>zVFr$zS6uAL(Fkl=Mg^>sOP#B;90+8mgiL@ZcL2-Z*pePM+
z95A$i7SPf|D`*ABBgzmbAX+2ZAUYtLL38~3DFsf1?TC%Akra{~k^>(jeusDsF&5Dq
z@fqS-L_O4#ERqFp!Z(Qj!hea2C?O?q8C(LRNXr1NNGsS3Yv5=2nUs;^$?@3p|j{q%(Aa3c?c}-bXxQHSp`KFNCqyTOQuG-j`k!+lj8&QM_Lp
zDb-1Twm!8!wsuHm+!k!V5ZR$uQWUK=@4yJM3UbATT#bK?RFi6qH05FsemzVuzp*~2
zP__%pt#`B`!cJi)U&VKn4#~UtwfvjHIKI90k=TX%NS_VetdHad=>zIH!cJma9~}+&
zk$SN`Qy&<*#XP8JlA#Zy5U&h9YfsiWdy2B7^aODPMxd{$G<&9Tqxd8_Pto8dGCN(~
ziXryUd7-47C*OL!CrASrKk_8hh#xcF
z%0VIv$O66!IAtYcD-B_6_1US|`mJm(F_+L**3aXP|=uBk$tc!%dVuUtQiMs>d8+yv2j5cuVVPk5N_%&7}2m
zgL%1d98`NfX1#P2pgl%-NS-31&*%f1W$A~}gH~dEzfV6*_K-cwj`E3IEjJ5$3`(Oh
zg*?FBsc78zc#jabiQDX%t}V=h`B;Mk)2$Wm9cjJa-r`JJD^wQF!Ri&wT*8gz#$xXZ
z;wNdzY9+Nd__fk3k9qNy?b-;
zYehXM4&r6?6Lp)gig^b4j(jIHQ+kHat5MoQ_+PrUQoc%BuP^r^?5UowJly^{cQ`%Q
z-h>Kat^7b@t+bz>%2(h^>MOKoz?X6ZIZUd{f17W8gImf$nt9{hwMz3tNgfpSK&X&FnJ2hrCecxv5B>`u?cGAO<}HG
z+4a;O;B##^tMFAouJUL)H%gOhCu0kRP-t}}=POssyNbKye?qy!bCj#ug?lF8+9O@A
z`T=t+h1HdDm9Ju)#Ium=ZpO9U5_X+CLc7AV@&d|L+o9F*J<{VE;>}kno~h2n{xCt&SbIsA
z+m_Tvt5AwyVP37dH3Dy@w?VnUo@tG7E6M#do@y7ue7Ql;V4+;Wok47lnAFZ21x3)E0v
zEf@9AYoBq-1dN&ekk43*10Rdm$>(B>`BuJF8K@7!_A#)1qV^C{^MPv02Uo4U)=%7?
zJ|C@4EhWR1Ysv4;3&VU)L{2BhwhxY1*gmA2cr{ey)#5He7?h71B4e?A7PyuA!`MFE
zv^wDhj3e!oGhwO6rwsX&MUa{gDJxP
zLQ-#Td~}S2$0#4^Ht4BQKDg#%@cGCE>VvZ7R>Jwm-wcnDkz_Kq&&A3!@RY~rsQXW;
zUHUDzj2|mZ!M&u~W8f3ap0qmsGM^95KROHDwYQ_$7@H^??%&)jt->0KD~62`P(J)>
z>~(#)>)c93BbEM`C^r<#YKiux$0r}#hwXddF?IWt+Mx1l#KUS!8?K6&h0vYwk{?ir5mW?!C$_>i0
z($>(8FT?)R2KnGhoFO$IL9iVO>|7S1ZP#|Sj#>wGznyQN63q0o?E*VbDpS9;Llp1;
z*60-Ozxi`>Cc-r1c=;PLRJm4MC|_Y-WNuWNhx!#dI5&3l>Tt&fp=^g`*&v)+pq3tn
zZaC_HLw5}rvc6Vs%vuqwzJ~iNXs(0&o;`_sD>8D}6YYtCT{qi*4eYwzzQw+YuBq+o
zDYWXQNeUowU=nQ?#?S?pklH
zQaevON4o)Bc?9lSy%6kOY2JKpf;@%E(hqy_psTrCKMWF`&v6fdOIdR#SqE^;3$LAy
zJmzJcPHNN{iYqTxy|qoiCaGQAHe|U=&Q?39qgCADAY;`h6d8RxC*pv7xilG&*T)+ovW9paP>kj
zzJ{M@-k?ke9#`5k%p0Url+~n$+or5h_NqKNr2R|X{lz`9URBDiR<*<>hIL6
zFzS5GRp^&U|DmJY(cst^$Q|=@^efd5_4~92%0TR>FFuBOM=hz0@KSogqwxU&PsRGw~|QKxipmAeU%=Q2wkvWem}uH1}G$+Q(L&
z`iuCY)y4fuz1(OJb=*%}BK$0tOOiZ>_55Q`Nm%CyeeZLb`En
zR&N^Jj|P;1aEs9_-RQ0k^SVvbhFI5V8N$_l66S?j!O?lW&UA9cax#YdDM)mm||`;1kGgIN2P
z?J{$a{EK~dRvY^=dy4&dwv}BWZo$3i8u`bpL)l%jyBk}@&c;@CRqTq#dCGZ8m7Hgs
zr=91VVE@f|(RtqS_TQXk3~ER%Q(I&&QCF*HtG(3TYNfHtk;#?9v$67A$8~T8)!qHQ
z+tck8w9wh^S#A%hOx)mx7<_rIOI9&?>SXng>Rswo*L4oNry9jZiR+qIThC`Nb%(mH
zJ6`xE))$UuK9T*VTkF1-m7l#i>tyR)p_{x!ZYaGa*5{0^+&pz8H;)4M!uuYBmhXI@
z%kGr@a`q?L-)m#ED{>&Gf6hb7Ol2ltmGfMVom0gv%DskLM4@ai?htE(GSk|v)#U!k
zb@PU5e-!_aH#qiwV;;xN6X)dqC4ahagK`PZBR|UV+e#Z?F*mv0A!_+C+XTIr26QW?wj{l7(>
z7d>8BRd{jX)%Nbf+l#iB%*cJ1j4GU+|4#m{+-Gv%$o)9?r@T+{elEH?Yi+)oUy@&u
z->cxQf}MK*{KI*w(Oj?B59BrfE$q^lWsl6hHv4XSch0B!{+vDfeln_HU*5^NR&J}@
zQ*#I856i#Gnx8$dAUFH9?9X%foR+zl2|esK!kGNY=EZvbZ(&o`saeDAKK2#%ZhM+N
z-(4gBNJc5o%Fig@s4di?>OIPF$^d&^?v$)aS+(}(_CY7lsc?4+wZ@lu{mm-qp0@@2O!tD5vKEJihsK9ygr3YfGv~qzAsNhTejA&ZE_*jikx?vl
zq@($lCTP>@CTP>zCTP>TCTP=!CTP>9CTP=}P0*&zP0uE)V-vKgQxml5fS$8)bo7nu*`kP)awuoJsxg*>WxQ8^uo$lV{
z-V^L0O>^&d@AUSNE^q_*D>L{!alHjZ~l_AOyzN$jNcgBO~QxyVRD_01SwX!mVm54t&_$m*DG|qShK39ul
zTg5rqIT_c>RZf4WuX9eYUOwIF=k)Z}%cnR2XsZ}geM#2+Qm0rc>9wuiGqG*;p3LrK
zDR!^1qkf=5kROe;%Rb#c9ruX(+P&?w?8;z|sE6IlMs~PI)SbciIqk3V}XtjGR>nde4knWtuNb?MM~#GheqwL64*x;u!$uMKRYmGOJnjK&LxevIrz1UWZ`_&$N+1BDjF4khkB{r2=ty$}mXbPejdUB954_NEunpj5GSJqeP
zJEASvimeB}W7?`MdA@@Wm3;V&z)sWyHe(c>%1n>;eWD)id!{Ekm6;yBSE3%h7t`aX
zXzfL=v3seH*5V9ps!L*19n+^rr83krCyAapVLef)4D}?5H+neUM5i*;vnmOnaQxMy
zQW@&mn?%pvaJ@yPGSss#iJpC7Jy9v~o=p0*(K=C&(VFRrPG!c&crA&Z*TQ!qIlw-n5%l(^4-
zLZm+FBb~XW*%G7aT>9<>Wnk8@6qL(5`Sm_4xie#@zM-E*pOj9=GI+dZGBqNm-
z9-pF98R}V^gwNVApQu!ZdNwD~v$^oEz9wsPSfiI>ZzZv-?8x%7b9PM34-=x-c=*)#
zCI79YPJL(@?RxEc`YpZ+fqvhDUP+mMAiZmCvNpx$XPT)b(G*_t&xMDy>-`jeuK)cj
zxswl;pGu14r;_O%`l;wF4?R-3{wGb*Hz9Fl_JQA{rQ4!&RtWS>NKfu&`bpvErxMg9
zxN1$3KURXTky=6XMe^zAX<}u
z4{o<@?cz9pIN%(>9RvE*k8PV&
zXQ{jhzmKIy_F`>|Z{=%9<;5^LRzq@o61|A&_kPI$Wx!#MJYgS#H*iv*Bk}Tdt*PpT3*xY!$p}EO!BRtdewX&9qwjn;9vZXTWg+(n{
z?HZqD)}M=T=IFPRSwwA5)l#Wu3LU%{T=afC??g$_{#zlimg=y9f|m9_c2qS$eUX;D_xnQLhwJCe`C(DZN7$Rd3-zN8g*%A?`wKi
z()Tq#kCsez@$I6oG@eehjpi?D@Js!AR+`1W#8j=5YMdxr*0}x2?iy>#eqpUswv3`e
z@a1U#rn8-2Wfr_LT65VlZLmBq`bzS2*|J|n_s7YlC%am<4Bq~gw0@c>KU2xYIJZ{M
zHcNhuS}{wb?Mu(kiXVr#@g!PSV`=7R_zO}9?Dd`;-_K~dRCc6_ncVcow87?7e#Y$J
zrc=OX`k6dta?>+f#lD!_K4kxPVjVWlCQ(x3`MqeA$us+H88Lr1qtfqXRQml)N}J6x
zD&0Jz(k(J7-O_56?sv_iy^6j)lDPyX(Y;q$8n<3k90k{FhNC%cobq73*3N0`wD#6(
zsuMsB88=ZW8A-S$1MR{7EMwC6(VCxurtMU=HNSBUUY^tBA8hZmM;|=N>FRWLx&%Jh$vM%fpgw3!i6G6AcNk%$S@LZoj5JHW
zV}y}jNpnyHX_l-u!zdjW_bs>de#`An5+K_9{cpJ?z9(mmpik}6{I$5LBmmVAy=ND#
z(Y(~W)L%n$YV`H^w0SA+UZ~b^YdEKJ*=bsG2MG`_HTgN!6MZNCSIzu;TsERGO-t?}
z0ivIeM(Z*sm=hBB6sV@Ob^VP5h?Y;&+zIhl@LIY|{!Rj_uaTqPGE&2r~)0n#itkPDDzxpTPyX_gzz1xT~pATB_f}@+0aBe}kHF^?vliD+dXskFMT}SFtA;5Hp@6x52+!g3l|FJAQ+j
z!(FJbE%cYSJsH7g+?xh$-!PS@&{C;w=8CyuR(~Zuqis&5zcB`>%B0p$r7`_cZ$}I#
zx5mzJj&$x@6|27#pBzTle*C!0&i(h2Xb<(@TVm&oY5aL&eX@OOYiaWN0=8=K%?~Cs
ze#V177`&Gh$>F`Hggw{qJLs0Y$A!TSHGlyEW@HlqHL}boA}EM)0VM`R5g3-l1%W6a
zg0ch%C^{^%={GK@fQCf{6=#l!AR=LrMFtfG5r_ty`?{(~(saOdKF;y{PIWC^@4o-N
z@4ltF3jpSv773Lx!Gymf6bytS>?9mGbVM>hApJl?22O6{{sv7T6JCcm;2C5jjDyk0Fqc6v5As|Vzydt#0{O^bWC<*V
zx8QAf2YSIMzmjU+=Tx($cnkd52~osb(L1@T7-gCf<%1|Rf+S|>RN
z&V}<_&IiRy@CjVtav>-#a=94Fxdaq-kV}!vkjs%Yq%Kkq`3uy>?VnXpA3lIZ$iI*R
zWF@i~c?EeBX^4zK9zkwKCLqruuOY?AY?z5WkGzYlMP~EabPoTgL3p9U=*f$C5q(L|
z(v$S|`a6NomgnQJuhf}WiM#{nNeQQ
zeB8=V`(%xiX6Qwld;@MVTEpGO33yN0!2BW_OCD=#|&0I}tBPFX(H|QC_e)v`l+I8>Kyf
z8MhMp>N{~nd=9sJ|3AFYab{X
zSsyb6Ga9|%46>}fDIb7jeT+kDW-~rD*0FY?q2~qN9Fv8c=^2S;;bxVEbPx0+U+FI!
zx!NwwzL!X2(wNr4EJPdFml}{p;b&na9(S(37jRG;=y>5}RLV{q?Oza0@w2V+qdcQ(
z;sx}jPg(7F31nbj%0e#+Fq;ar?;J0@jDkX}<8UHgSchec~q)`$w+zWcYkp3;k)uyWm`nHpqXguN>`N
zg)0s3ywESW*W^olEG8MlNY=&7(!yVi->{
zT;u)~wWKKHYcMYETv8L|YW5&Eu(iAxm0wO8!@cBH
zZHJ!iDAxw@Is6Mgpa0vzc;d{nAS$o#DCZa1wpsh90Etp(HgK_VAvt$HOX&hZclh^pJiF9iVkK(%A3p8PK_`JVP0)$yB(F
z{tAqAH133F!mD{3k3@VTWsrvBof?gbNdtLYyF|>B$K`R=gJ~_AVP6z{&{$w>qh)NB
zRp^^dOZDY!m9ZL1aNB}DZSjcbkyVI3VVtziY_0aWz8ntlCdmBCKCvFg1HlLBJM6~P
z_UtZwpgs&&6E2DPWUlmlGEPK>ut(YJyaD@GgkY+%%D6^M;TOX~G98*>uhgwVHi4Gn
z>O*Hepai$W=+j}3s(jLNv>e(;>q6hq*OR-%cJ{rvp|VfLK|Yo1yq7={@Kv7HY7
zvD`DSm!)QrIm>+8s%P!9+L|k3eWLxf1;$18<#yk|4Z%IITx-QAdnDqMHV#MB!OAC?
z52gCG#t_m$f5r5r_-tx!uohZ%tpipEyE82lEwP>6rls}}Ut8KAN^skY?X=gUs&?`Z
z2(+~NSY!Dp>l5EF-*h|MZKYfhh1~C3rSday6|1bf4WXleL(
z_;+52v0Co+vD57nQ$_cY<3>-V${b-%2;Pu%9ly=DQ5#_Nqvz6$5y!}V
z)(=jN)(q>v)=Yg9D`YRQS)?oJYPP2jCEo#Wo-M`ZVJkg!AX!gokGRuOzQZxsRLNP8yvuEc9;DtfaS+{++Zt`JCj2Vwd$@^2X%vH@?-|bwUMU@>-Q8`kMM3qm<0y$cabyYqs
z$H=FmDo05dU!JeXQOU}D%Yv`+^gpA@;D17$T$RUZerOW1UjTK988ZR>bBl|BNalsgZM|DmO&xh;Cv6Z}n$X>Dv|B
z5LNj_pu6vc|6G2}pHZd%O8-q!l^cUUC;6?8y!BaBxidB|r6x7ZOG8r0rF8qaDTQRw
zKCVlb6cQL@Ok|q^ldZni)7B#1=g+9pTIcVBD!&Zrfj3hQB>l$wvRV2yu|C^V>?uZp
zy~qB>{?>P;PsbGp6L1D3>})A64jqSD2Yw3rgI6TgP0cO`mQ;7G
z!297^p$qBa*nlN8InhYadGRAb=P8WYv3B_;zR4)yTliOeE8pfsnD5{v{A(3qzS)D-
zk8hXNSCso+`H0SAzStT?Bhd)gX-!0i=qc`Z$Jah0N8F?GnB3^0EY(CY&yBB`=PFoz
zF(y`-ubHozQQ#}|weU^z6}j0q!#CYGRmH;B+=EZ7!tz9pBpzcvsS3N3xFXkhFjg_2
z%jaV2ea=7S3;8;?^XiQ8qF@$Irqg|V5>5xw|)t&ao#a`^|_!59_at}!Y~!f{|#WDc98s6ia2#MjHF
zC~9DLS`~JuF{B1|r&nQjIzx2zi*u!CQPEfQ#j)sN(O(P{gWa)cs2C&$sQx1!@*sKf
z?c(*k8mO&etY-5R@q3H9O7d$^XK{Q_Sg}H15F4RCn%V5bD(rs9ki_+Jh;LWDTEao!
zmZ)AXs<10KQUkqptFT*_BQ>zwunM~kIg+?tQpE_4*OA2S^1)T;9n6s$*d1Dh-Ju*2
zU1IaWZeh2;735@llHJyx;Pi02wLRW$qgESsOApnr)Y?Aw*CsMVTgYdN-m!0M7zL+$
zTf^zQ>UTBgh_7+>6+fX<@$}`9_u~`8A$d?9
zkUu%T%kSln@`vaX!*|j}*@*R>6LpoXBpGU-NDSBtEWg5u0sYL=S#hs-^J0*iUA-9S
z-Hfh|{}p4v2Z;+#iNVkEXN7wjajse#kt!!nr*RX#l
zE__gGHXp=?pQ37kT!5;!$r8CmZgo{Hl3&ZOqN)~37p0)0Dt5x|6KhNTYg(Ob47I8J
zKN-H~a-XWle!y!RU(-Ztftyu%)!vZiSvuX`*RTkaR&cbtQGHzHBKbO3h|*>r6S2b^T2k@7QUr(Tx^~?opnZnlN
zmhjWN(t*##N2{H4Hxrj?m+VAbs$H@pajAC64#cI}C3_H;YL~p7xKz7jcj987ADe&G
z?R`$3h5hCER`E#nL^xh;eYX%7^-n71<CsU&Fs@y|G`7uUN;a$0^Zy=+x_}*l$vdh
zi)UF~Qx*X0Rcc&Me^%${Wu|jZwmN0;-N(OSU74ybRmM}JVuNR>#<{~Br;XP~L~UF8
zjrwbj?ed!NJy+XP!#8?I&Yo{nCHTgu8oW#0sqWz$JvClCICaq@j^|*h@>qI_XAydP
zM_vsT&m*ry@2*srW1(_g;pne0PFOLoK?Cr{NgH;vl!qTz!Q6G8BEt4MO
ze>(lm_&7DaJY(3}sETyQFI+=xg}LfVc{!M?%D~+6GEP>(-12)=32RE!5*}5g@>RGl
zH60eDrX$h2M5@~3)kwZd^GuVv1U!6l^{Os{R
D@UeHw
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser10.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
index 57084e83b61758d20fe1cb0e70ee7a3f89f76b7d..082965aaf83df322d5db97ae922b1a16ac4891c0 100644
GIT binary patch
literal 266
zcmXxZF(?FJ7{>Ac|Eo)xu22S-l5%yS8{Fhdk?yjcNirB@WIO`{MO})zi85UVli`#k
z8IF=g78$M#GAM&d7V+ii*W3F%@5?Mpe3>`T1-IPu%7=G0{R|0Cx#Hb+7u}B@eDgbW
zSg^pBSref*q>(m~Y_P)-$JBY`i5Gj^^xVsk4O8(y!YGG!Ip9iEi}(I8Xf>vqB}*)j
zW{oOMllGZ$$egS0TJbteTM6TIvu!R+x=be-#(tG4lVZf?STfi%gfkpt
z_{C_-Xvx6Iki@VP2%j?QG8!^mWq1mNlYr2SL4YBaA(J7Gp^RZK!zG3@4F4Ee7;Ql`
XP^OGw1H&PPZwx;e7#SEDg&BnbiH;m8
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser11.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
index 4ed7d3b5b2df1a2b4c9769f1662bc0bf8173fed1..d1a5283b00e13d6fe214a1b3ca78e730bebc6068 100644
GIT binary patch
literal 266
zcmYj~KMMf?7{;IHt((qGN?kXclF?u=Tq&hk)KThEiefUDY%)+*D}#Y77MIP3xO@xw
z0zQHF{wV!=d;dM}^TL3_7Kd?8;XLK9KlApR(&q>!3VNkF)tE_`2onsv@M2M?DFs;Y
zVrVP+M?YDK*MV2w8E}GG<`FW_vN|hV{~Wl3qgeFdaG|>jn(z@|i4`_Da+_U5jN(d$
nGDaI6^w7rudz^6LQ#`3lAXB(}NKG1WrHc}(DDfjU-;(I1<8P}Lwk=NTCpgc&LsHZvRn%P}*sF^V#(0|3)W9{vCT
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
index a114c91f3fa2627c870bb34b24218617a6814a2b..955f911d6f46c4fbacfa557fda70b2175b2f2682 100644
GIT binary patch
literal 266
zcmX|+y=nqM6otQe02c*|?GzRa79v*K83Zc}O%xS0vfxh?L<>>U)G=@w$4_9&LDqj@ts(6(}$@3*x5m%Nd
zL5+`q&`>6iELqc&_o)!&LY;4($cyeaRCKD_Y^#`xNWvR_8oW@G^qn##~`d;08*a+w94_-N+O#`Q8i%B??DSv~1+0
xKju@(>RTK%T(Jf^X)m!gD-XB5fov@=H8T;RDL?Fo5%T~5
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
index 6b56156124670f0e4d308a77c588208530484c08..9dc419e05f83eb849d852f5027bf93f27bad8b38 100644
GIT binary patch
literal 266
zcmYk1Jqp555QJwCLONSPEQ5%GjbLRV>2iUbA&^qE%{hW?Ztx1hQ;1baA&3WYcAo(m
z-m*Wl-||?oLXU^XUYSJoOtG@s=A+!3+0;7?ayH1M-*zM*!5t~~D3IeQHJFVYq><$$
zCu51Z2-CmY6d}P5Tg4Lt>|(9Gz>Y5teERl*9VY6Yp{M*J&y_d6Ibb8t3MJQ4i-jny
QCV?NzQKJyGbf*993(K`Xpa1{>
literal 128
zcmZQ@W+-Rqfx>bI5Dx|+Y?vH`E@xn4&|{EeP+>R-REMq_#ODW^1v7yWsG5y|gF%`>
T0!%Lj%P<4UCI&Ac1gZl7niUud
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/src/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
index e701a9e70029486cd2e16e08d063ed95458d3e05..ecfa0217c356244cba591a70815292ef67e4e095 100644
GIT binary patch
literal 1228
zcmZ9M&x?&=6vw}(8;#8@Y-H}3a^3LWncFBUrMR<0Mi_&{3JVIWu|SilOI9QyX>P>D
zR!H`mcW~2EVWMSiT&hx%A_npQ0{e91m=Q+Z_rbyt*zRCd{=1pAinH`1-ITXy1+SH)_cW|&pJx$w2waMOq80)DfnMR0
z_ht>cWo~O|DAyM4-0!C{7IS~rRb+74Q9qS4-DOrq7nv@E?ltDsMZcQonqQ_bRY|yB+p{fYkR8`0>NN5G
zBkw6>UGMSSu